Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 31 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Apply List To Co... | 19986191 | 34 days ago | IN | 0 ETH | 0.00037198 | ||||
Set Transfer Sec... | 19980006 | 35 days ago | IN | 0 ETH | 0.00041317 | ||||
Apply List To Co... | 19344383 | 124 days ago | IN | 0 ETH | 0.00172814 | ||||
Create List | 19344374 | 124 days ago | IN | 0 ETH | 0.00247473 | ||||
Set Transfer Sec... | 19344358 | 124 days ago | IN | 0 ETH | 0.00148977 | ||||
Set Transfer Sec... | 19343591 | 124 days ago | IN | 0 ETH | 0.00131266 | ||||
Add Accounts To ... | 19323302 | 127 days ago | IN | 0 ETH | 0.0182611 | ||||
Create List | 19320983 | 128 days ago | IN | 0 ETH | 0.00309127 | ||||
Add Accounts To ... | 19313484 | 129 days ago | IN | 0 ETH | 0.00538008 | ||||
Add Accounts To ... | 19235607 | 140 days ago | IN | 0 ETH | 0.00703049 | ||||
Add Accounts To ... | 19232314 | 140 days ago | IN | 0 ETH | 0.00318203 | ||||
Remove Accounts ... | 19232302 | 140 days ago | IN | 0 ETH | 0.00072994 | ||||
Add Code Hashes ... | 19232286 | 140 days ago | IN | 0 ETH | 0.00213208 | ||||
Remove Code Hash... | 19232280 | 140 days ago | IN | 0 ETH | 0.00077116 | ||||
Add Accounts To ... | 19232269 | 140 days ago | IN | 0 ETH | 0.00193856 | ||||
Add Accounts To ... | 19231885 | 140 days ago | IN | 0 ETH | 0.00211519 | ||||
Add Accounts To ... | 19231833 | 140 days ago | IN | 0 ETH | 0.00265918 | ||||
Remove Code Hash... | 19231680 | 140 days ago | IN | 0 ETH | 0.00072388 | ||||
Add Accounts To ... | 19218118 | 142 days ago | IN | 0 ETH | 0.00236664 | ||||
Remove Accounts ... | 19217883 | 142 days ago | IN | 0 ETH | 0.00077728 | ||||
Add Operator To ... | 19217875 | 142 days ago | IN | 0 ETH | 0.00240831 | ||||
Add Code Hashes ... | 19217589 | 142 days ago | IN | 0 ETH | 0.0019229 | ||||
Remove Accounts ... | 19217311 | 142 days ago | IN | 0 ETH | 0.00065661 | ||||
Remove Code Hash... | 19217308 | 142 days ago | IN | 0 ETH | 0.00064896 | ||||
Add Code Hashes ... | 19217265 | 142 days ago | IN | 0 ETH | 0.00196808 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
19143530 | 153 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
CreatorTokenTransferValidatorV2
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./EOARegistry.sol"; import "../interfaces/IOwnable.sol"; import "../interfaces/ICreatorTokenTransferValidator.sol"; import "../interfaces/ICreatorTokenTransferValidatorV2.sol"; import "@openzeppelin/contracts/access/IAccessControl.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /** * @title CreatorTokenTransferValidatorV2 * @author Limit Break, Inc. * @notice The CreatorTokenTransferValidatorV2 contract is designed to provide a customizable and secure transfer * validation mechanism for NFT collections. This contract allows the owner of an NFT collection to configure * the transfer security level, blacklisted accounts and codehashes and whitelisted accounts and codehashes * for each collection. * * @dev <h4>Features</h4> * - Transfer security levels: Provides different levels of transfer security, * from open transfers to completely restricted transfers. * - Blacklist: Allows the owner of a collection to blacklist specific operator addresses or codehashes * from executing transfers on behalf of others. * - Whitelist: Allows the owner of a collection to whitelist specific operator addresses or codehashes * permitted to execute transfers on behalf of others or send/receive tokens when otherwise disabled by * security policy. * * @dev <h4>Benefits</h4> * - Enhanced security: Allows creators to have more control over their NFT collections, ensuring the safety * and integrity of their assets. * - Flexibility: Provides collection owners the ability to customize transfer rules as per their requirements. * - Compliance: Facilitates compliance with regulations by enabling creators to restrict transfers based on * specific criteria. * * @dev <h4>Intended Usage</h4> * - The CreatorTokenTransferValidatorV2 contract is intended to be used by NFT collection owners to manage and * enforce transfer policies. This contract is integrated with the following varations of creator token * NFT contracts to validate transfers according to the defined security policies. * * - ERC721-C: Creator token implenting OpenZeppelin's ERC-721 standard. * - ERC721-AC: Creator token implenting Azuki's ERC-721A standard. * - ERC721-CW: Creator token implementing OpenZeppelin's ERC-721 standard with opt-in staking to * wrap/upgrade a pre-existing ERC-721 collection. * - ERC721-ACW: Creator token implementing Azuki's ERC721-A standard with opt-in staking to * wrap/upgrade a pre-existing ERC-721 collection. * - ERC1155-C: Creator token implenting OpenZeppelin's ERC-1155 standard. * - ERC1155-CW: Creator token implementing OpenZeppelin's ERC-1155 standard with opt-in staking to * wrap/upgrade a pre-existing ERC-1155 collection. * * <h4>Transfer Security Levels</h4> * - Recommended: Recommended defaults are same as Level 3 (Whitelisting with OTC Enabled). * - Caller Constraints: OperatorWhitelistEnableOTC * - Receiver Constraints: None * - Level 1: No transfer restrictions. * - Caller Constraints: None * - Receiver Constraints: None * - Level 2: Only non-blacklisted operators can initiate transfers, over-the-counter (OTC) trading enabled. * - Caller Constraints: OperatorBlacklistEnableOTC * - Receiver Constraints: None * - Level 3: Only whitelisted accounts can initiate transfers, over-the-counter (OTC) trading enabled. * - Caller Constraints: OperatorWhitelistEnableOTC * - Receiver Constraints: None * - Level 4: Only whitelisted accounts can initiate transfers, over-the-counter (OTC) trading disabled. * - Caller Constraints: OperatorWhitelistDisableOTC * - Receiver Constraints: None * - Level 5: Only whitelisted accounts can initiate transfers, over-the-counter (OTC) trading enabled. * Transfers to contracts with code are not allowed, unless present on the whitelist. * - Caller Constraints: OperatorWhitelistEnableOTC * - Receiver Constraints: NoCode * - Level 6: Only whitelisted accounts can initiate transfers, over-the-counter (OTC) trading enabled. * Transfers are allowed only to Externally Owned Accounts (EOAs), unless present on the whitelist. * - Caller Constraints: OperatorWhitelistEnableOTC * - Receiver Constraints: EOA * - Level 7: Only whitelisted accounts can initiate transfers, over-the-counter (OTC) trading disabled. * Transfers to contracts with code are not allowed, unless present on the whitelist. * - Caller Constraints: OperatorWhitelistDisableOTC * - Receiver Constraints: NoCode * - Level 8: Only whitelisted accounts can initiate transfers, over-the-counter (OTC) trading disabled. * Transfers are allowed only to Externally Owned Accounts (EOAs), unless present on the whitelist. * - Caller Constraints: OperatorWhitelistDisableOTC * - Receiver Constraints: EOA */ contract CreatorTokenTransferValidatorV2 is EOARegistry, ICreatorTokenTransferValidatorV2 { using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.Bytes32Set; // Custom Errors /// @dev Thrown when an array that cannot be zero length is supplied with zero length. error CreatorTokenTransferValidator__ArrayLengthCannotBeZero(); /// @dev Thrown when attempting to set a list id that does not exist. error CreatorTokenTransferValidator__ListDoesNotExist(); /// @dev Thrown when attempting to transfer the ownership of a list to the zero address. error CreatorTokenTransferValidator__ListOwnershipCannotBeTransferredToZeroAddress(); /// @dev Thrown when attempting to call a function that requires the caller to be the list owner. error CreatorTokenTransferValidator__CallerDoesNotOwnList(); /// @dev Thrown when validating a transfer for a collection using whitelists and the operator is not on the whitelist. error CreatorTokenTransferValidator__CallerMustBeWhitelisted(); /// @dev Thrown when attempting to call a function that requires owner or default admin role for a collection that the caller does not have. error CreatorTokenTransferValidator__CallerMustHaveElevatedPermissionsForSpecifiedNFT(); /// @dev Thrown when validating a transfer for a collection using blacklists and the operator is on the blacklist. error CreatorTokenTransferValidator__OperatorIsBlacklisted(); /// @dev Thrown when validating a transfer for a collection that does not allow receiver to have code and the receiver has code. error CreatorTokenTransferValidator__ReceiverMustNotHaveDeployedCode(); /// @dev Thrown when validating a transfer for a collection that requires receivers be verified EOAs and the receiver is not verified. error CreatorTokenTransferValidator__ReceiverProofOfEOASignatureUnverified(); /// @dev Thrown when attempting to add the zero address to a whitelist or blacklist. error CreatorTokenTransferValidator__ZeroAddressNotAllowed(); /// @dev Thrown when attempting to add the zero code hash to a whitelist or blacklist. error CreatorTokenTransferValidator__ZeroCodeHashNotAllowed(); // Structs /** * @dev This struct is internally for the storage of account and codehash lists. */ struct List { EnumerableSet.AddressSet enumerableAccounts; EnumerableSet.Bytes32Set enumerableCodehashes; mapping (address => bool) nonEnumerableAccounts; mapping (bytes32 => bool) nonEnumerableCodehashes; } // Constants /// @dev The default admin role value for contracts that implement access control. bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00; /// @dev Value representing a zero value code hash. bytes32 private constant CODEHASH_ZERO = 0x0000000000000000000000000000000000000000000000000000000000000000; /// @notice Keeps track of the most recently created list id. uint120 public lastListId; /// @notice Mapping of list ids to list owners mapping (uint120 => address) public listOwners; /// @dev Mapping of collection addresses to their security policy settings mapping (address => CollectionSecurityPolicyV2) private collectionSecurityPolicies; /// @dev Mapping of list ids to blacklist settings mapping (uint120 => List) private blacklists; /// @dev Mapping of list ids to whitelist settings mapping (uint120 => List) private whitelists; constructor(address defaultOwner) EOARegistry() { uint120 id = 0; listOwners[id] = defaultOwner; emit CreatedList(id, "DEFAULT LIST"); emit ReassignedListOwnership(id, defaultOwner); } /*************************************************************************/ /* MODIFIERS */ /*************************************************************************/ /** * @dev This modifier restricts a function call to the owner of the list `id`. * @dev Throws when the caller is not the list owner. */ modifier onlyListOwner(uint120 id) { _requireCallerOwnsList(id); _; } /** * @dev This modifier reverts a transaction if the supplied array has a zero length. * @dev Throws when the array parameter has a zero length. */ modifier notZero(uint256 value) { if (value == 0) { revert CreatorTokenTransferValidator__ArrayLengthCannotBeZero(); } _; } /*************************************************************************/ /* APPLY TRANSFER POLICIES */ /*************************************************************************/ /** * @notice Apply the collection transfer policy to a transfer operation of a creator token. * * @dev Throws when the receiver has deployed code and isn't whitelisted, if ReceiverConstraints.NoCode is set. * @dev Throws when the receiver has never verified a signature to prove they are an EOA and the receiver * isn't whitelisted, if the ReceiverConstraints.EOA is set. * @dev Throws when `msg.sender` is blacklisted, if CallerConstraints.OperatorBlacklistEnableOTC is set, unless * `msg.sender` is also the `from` address. * @dev Throws when `msg.sender` isn't whitelisted, if CallerConstraints.OperatorWhitelistEnableOTC is set, unless * `msg.sender` is also the `from` address. * @dev Throws when neither `msg.sender` nor `from` are whitelisted, if * CallerConstraints.OperatorWhitelistDisableOTC is set. * * @dev <h4>Postconditions:</h4> * 1. Transfer is allowed or denied based on the applied transfer policy. * * @param caller The address initiating the transfer. * @param from The address of the token owner. * @param to The address of the token receiver. */ function applyCollectionTransferPolicy(address caller, address from, address to) external view override { CollectionSecurityPolicyV2 storage collectionSecurityPolicy = collectionSecurityPolicies[_msgSender()]; uint120 listId = collectionSecurityPolicy.listId; (CallerConstraints callerConstraints, ReceiverConstraints receiverConstraints) = transferSecurityPolicies(collectionSecurityPolicy.transferSecurityLevel); List storage whitelist = whitelists[listId]; if (receiverConstraints == ReceiverConstraints.NoCode) { if (_getCodeLengthAsm(to) > 0) { if (!whitelist.nonEnumerableAccounts[to]) { if (!whitelist.nonEnumerableCodehashes[_getCodeHashAsm(to)]) { revert CreatorTokenTransferValidator__ReceiverMustNotHaveDeployedCode(); } } } } else if (receiverConstraints == ReceiverConstraints.EOA) { if (!isVerifiedEOA(to)) { if (!whitelist.nonEnumerableAccounts[to]) { if (!whitelist.nonEnumerableCodehashes[_getCodeHashAsm(to)]) { revert CreatorTokenTransferValidator__ReceiverProofOfEOASignatureUnverified(); } } } } if (caller == from) { if (callerConstraints != CallerConstraints.OperatorWhitelistDisableOTC) { return; } } if (callerConstraints == CallerConstraints.OperatorBlacklistEnableOTC) { List storage blacklist = blacklists[listId]; if (blacklist.nonEnumerableAccounts[caller]) { revert CreatorTokenTransferValidator__OperatorIsBlacklisted(); } if (blacklist.nonEnumerableCodehashes[_getCodeHashAsm(caller)]) { revert CreatorTokenTransferValidator__OperatorIsBlacklisted(); } } else if (callerConstraints == CallerConstraints.OperatorWhitelistEnableOTC) { if (whitelist.nonEnumerableAccounts[caller]) { return; } if (whitelist.nonEnumerableCodehashes[_getCodeHashAsm(caller)]) { return; } revert CreatorTokenTransferValidator__CallerMustBeWhitelisted(); } else if (callerConstraints == CallerConstraints.OperatorWhitelistDisableOTC) { mapping(address => bool) storage accountWhitelist = whitelist.nonEnumerableAccounts; if (accountWhitelist[caller]) { return; } if (accountWhitelist[from]) { return; } mapping(bytes32 => bool) storage codehashWhitelist = whitelist.nonEnumerableCodehashes; if (codehashWhitelist[_getCodeHashAsm(caller)]) { return; } if (codehashWhitelist[_getCodeHashAsm(from)]) { return; } revert CreatorTokenTransferValidator__CallerMustBeWhitelisted(); } } /** * @notice Returns the caller and receiver constraints for the specified transfer security level. * * @param level The transfer security level to return the caller and receiver constraints for. * * @return callerConstraints The `CallerConstraints` enum value for the level. * @return receiverConstraints The `ReceiverConstraints` enum value for the level. */ function transferSecurityPolicies(TransferSecurityLevels level) public pure returns (CallerConstraints callerConstraints, ReceiverConstraints receiverConstraints) { if (level == TransferSecurityLevels.Recommended) { callerConstraints = CallerConstraints.OperatorWhitelistEnableOTC; receiverConstraints = ReceiverConstraints.None; } else if (level == TransferSecurityLevels.One) { callerConstraints = CallerConstraints.None; receiverConstraints = ReceiverConstraints.None; } else if (level == TransferSecurityLevels.Two) { callerConstraints = CallerConstraints.OperatorBlacklistEnableOTC; receiverConstraints = ReceiverConstraints.None; } else if (level == TransferSecurityLevels.Three) { callerConstraints = CallerConstraints.OperatorWhitelistEnableOTC; receiverConstraints = ReceiverConstraints.None; } else if (level == TransferSecurityLevels.Four) { callerConstraints = CallerConstraints.OperatorWhitelistDisableOTC; receiverConstraints = ReceiverConstraints.None; } else if (level == TransferSecurityLevels.Five) { callerConstraints = CallerConstraints.OperatorWhitelistEnableOTC; receiverConstraints = ReceiverConstraints.NoCode; } else if (level == TransferSecurityLevels.Six) { callerConstraints = CallerConstraints.OperatorWhitelistEnableOTC; receiverConstraints = ReceiverConstraints.EOA; } else if (level == TransferSecurityLevels.Seven) { callerConstraints = CallerConstraints.OperatorWhitelistDisableOTC; receiverConstraints = ReceiverConstraints.NoCode; } else { callerConstraints = CallerConstraints.OperatorWhitelistDisableOTC; receiverConstraints = ReceiverConstraints.EOA; } } /*************************************************************************/ /* LIST MANAGEMENT */ /*************************************************************************/ /** * @notice Creates a new list id. The list id is a handle to allow editing of blacklisted and whitelisted accounts * and codehashes. * * @dev <h4>Postconditions:</h4> * 1. A new list with the specified name is created. * 2. The caller is set as the owner of the new list. * 3. A `CreatedList` event is emitted. * 4. A `ReassignedListOwnership` event is emitted. * * @param name The name of the new list. * @return The id of the new list. */ function createList(string calldata name) public override returns (uint120) { uint120 id = ++lastListId; listOwners[id] = _msgSender(); emit CreatedList(id, name); emit ReassignedListOwnership(id, _msgSender()); return id; } /** * @notice Creates a new list id, and copies all blacklisted and whitelisted accounts and codehashes from the * specified source list. * * @dev <h4>Postconditions:</h4> * 1. A new list with the specified name is created. * 2. The caller is set as the owner of the new list. * 3. A `CreatedList` event is emitted. * 4. A `ReassignedListOwnership` event is emitted. * 5. All blacklisted and whitelisted accounts and codehashes from the specified source list are copied * to the new list. * 6. An `AddedAccountToList` event is emitted for each blacklisted and whitelisted account copied. * 7. An `AddedCodeHashToList` event is emitted for each blacklisted and whitelisted codehash copied. * * @param name The name of the new list. * @param sourceListId The id of the source list to copy from. * @return The id of the new list. */ function createListCopy(string calldata name, uint120 sourceListId) external override returns (uint120) { uint120 id = ++lastListId; unchecked { if (sourceListId > id - 1) { revert CreatorTokenTransferValidator__ListDoesNotExist(); } } listOwners[id] = _msgSender(); emit CreatedList(id, name); emit ReassignedListOwnership(id, _msgSender()); List storage sourceBlacklist = blacklists[sourceListId]; List storage sourceWhitelist = whitelists[sourceListId]; List storage targetBlacklist = blacklists[id]; List storage targetWhitelist = whitelists[id]; _copyAddressSet(ListTypes.Blacklist, id, sourceBlacklist, targetBlacklist); _copyBytes32Set(ListTypes.Blacklist, id, sourceBlacklist, targetBlacklist); _copyAddressSet(ListTypes.Whitelist, id, sourceWhitelist, targetWhitelist); _copyBytes32Set(ListTypes.Whitelist, id, sourceWhitelist, targetWhitelist); return id; } /** * @notice Transfer ownership of a list to a new owner. * * @dev Throws when the new owner is the zero address. * @dev Throws when the caller does not own the specified list. * * @dev <h4>Postconditions:</h4> * 1. The list ownership is transferred to the new owner. * 2. A `ReassignedListOwnership` event is emitted. * * @param id The id of the list. * @param newOwner The address of the new owner. */ function reassignOwnershipOfList(uint120 id, address newOwner) public override { if(newOwner == address(0)) { revert CreatorTokenTransferValidator__ListOwnershipCannotBeTransferredToZeroAddress(); } _reassignOwnershipOfList(id, newOwner); } /** * @notice Renounce the ownership of a list, rendering the list immutable. * * @dev Throws when the caller does not own the specified list. * * @dev <h4>Postconditions:</h4> * 1. The ownership of the specified list is renounced. * 2. A `ReassignedListOwnership` event is emitted. * * @param id The id of the list. */ function renounceOwnershipOfList(uint120 id) public override { _reassignOwnershipOfList(id, address(0)); } /** * @notice Set the transfer security level of a collection. * * @dev Throws when the caller is neither collection contract, nor the owner or admin of the specified collection. * * @dev <h4>Postconditions:</h4> * 1. The transfer security level of the specified collection is set to the new value. * 2. A `SetTransferSecurityLevel` event is emitted. * * @param collection The address of the collection. * @param level The new transfer security level to apply. */ function setTransferSecurityLevelOfCollection( address collection, TransferSecurityLevels level) external override { _requireCallerIsNFTOrContractOwnerOrAdmin(collection); collectionSecurityPolicies[collection].transferSecurityLevel = level; emit SetTransferSecurityLevel(collection, level); } /** * @notice Applies the specified list to a collection. * * @dev Throws when the caller is neither collection contract, nor the owner or admin of the specified collection. * @dev Throws when the specified list id does not exist. * * @dev <h4>Postconditions:</h4> * 1. The list of the specified collection is set to the new value. * 2. An `AppliedListToCollection` event is emitted. * * @param collection The address of the collection. * @param id The id of the operator whitelist. */ function applyListToCollection(address collection, uint120 id) public override { _requireCallerIsNFTOrContractOwnerOrAdmin(collection); if (id > lastListId) { revert CreatorTokenTransferValidator__ListDoesNotExist(); } collectionSecurityPolicies[collection].listId = id; emit AppliedListToCollection(collection, id); } /** * @notice Get the security policy of the specified collection. * @param collection The address of the collection. * @return The security policy of the specified collection, which includes: * Transfer security level, operator whitelist id, permitted contract receiver allowlist id */ function getCollectionSecurityPolicyV2(address collection) external view override returns (CollectionSecurityPolicyV2 memory) { return collectionSecurityPolicies[collection]; } /** * @notice Adds one or more accounts to a blacklist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the accounts array is empty. * * @dev <h4>Postconditions:</h4> * 1. Accounts not previously in the list are added. * 2. An `AddedAccountToList` event is emitted for each account that is newly added to the list. * * @param id The id of the list. * @param accounts The addresses of the accounts to add. */ function addAccountsToBlacklist( uint120 id, address[] calldata accounts ) external override onlyListOwner(id) notZero(accounts.length) { List storage blacklist = blacklists[id]; address account; for (uint256 i = 0; i < accounts.length;) { account = accounts[i]; if (account == address(0)) { revert CreatorTokenTransferValidator__ZeroAddressNotAllowed(); } if (blacklist.enumerableAccounts.add(account)) { emit AddedAccountToList(ListTypes.Blacklist, id, account); blacklist.nonEnumerableAccounts[account] = true; } unchecked { ++i; } } } /** * @notice Adds one or more accounts to a whitelist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the accounts array is empty. * * @dev <h4>Postconditions:</h4> * 1. Accounts not previously in the list are added. * 2. An `AddedAccountToList` event is emitted for each account that is newly added to the list. * * @param id The id of the list. * @param accounts The addresses of the accounts to add. */ function addAccountsToWhitelist( uint120 id, address[] calldata accounts ) external override onlyListOwner(id) notZero(accounts.length) { List storage whitelist = whitelists[id]; address account; for (uint256 i = 0; i < accounts.length;) { account = accounts[i]; if (account == address(0)) { revert CreatorTokenTransferValidator__ZeroAddressNotAllowed(); } if (whitelist.enumerableAccounts.add(account)) { emit AddedAccountToList(ListTypes.Whitelist, id, account); whitelist.nonEnumerableAccounts[account] = true; } unchecked { ++i; } } } /** * @notice Adds one or more codehashes to a blacklist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the codehashes array is empty. * @dev Throws when a codehash is zero. * * @dev <h4>Postconditions:</h4> * 1. Codehashes not previously in the list are added. * 2. An `AddedCodeHashToList` event is emitted for each codehash that is newly added to the list. * * @param id The id of the list. * @param codehashes The codehashes to add. */ function addCodeHashesToBlacklist( uint120 id, bytes32[] calldata codehashes ) external override onlyListOwner(id) notZero(codehashes.length) { List storage blacklist = blacklists[id]; bytes32 codehash; for (uint256 i = 0; i < codehashes.length;) { codehash = codehashes[i]; if (codehash == CODEHASH_ZERO) { revert CreatorTokenTransferValidator__ZeroCodeHashNotAllowed(); } if (blacklist.enumerableCodehashes.add(codehash)) { emit AddedCodeHashToList(ListTypes.Blacklist, id, codehash); blacklist.nonEnumerableCodehashes[codehash] = true; } unchecked { ++i; } } } /** * @notice Adds one or more codehashes to a whitelist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the codehashes array is empty. * @dev Throws when a codehash is zero. * * @dev <h4>Postconditions:</h4> * 1. Codehashes not previously in the list are added. * 2. An `AddedCodeHashToList` event is emitted for each codehash that is newly added to the list. * * @param id The id of the list. * @param codehashes The codehashes to add. */ function addCodeHashesToWhitelist( uint120 id, bytes32[] calldata codehashes ) external override onlyListOwner(id) notZero(codehashes.length) { List storage whitelist = whitelists[id]; bytes32 codehash; for (uint256 i = 0; i < codehashes.length;) { codehash = codehashes[i]; if (codehash == CODEHASH_ZERO) { revert CreatorTokenTransferValidator__ZeroCodeHashNotAllowed(); } if (whitelist.enumerableCodehashes.add(codehash)) { emit AddedCodeHashToList(ListTypes.Whitelist, id, codehash); whitelist.nonEnumerableCodehashes[codehash] = true; } unchecked { ++i; } } } /** * @notice Removes one or more accounts from a blacklist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the accounts array is empty. * * @dev <h4>Postconditions:</h4> * 1. Accounts previously in the list are removed. * 2. A `RemovedAccountFromList` event is emitted for each account that is removed from the list. * * @param id The id of the list. * @param accounts The addresses of the accounts to remove. */ function removeAccountsFromBlacklist( uint120 id, address[] calldata accounts ) external override onlyListOwner(id) notZero(accounts.length) { List storage blacklist = blacklists[id]; address account; for (uint256 i = 0; i < accounts.length;) { account = accounts[i]; if (blacklist.enumerableAccounts.remove(account)) { emit RemovedAccountFromList(ListTypes.Blacklist, id, account); delete blacklist.nonEnumerableAccounts[account]; } unchecked { ++i; } } } /** * @notice Removes one or more accounts from a whitelist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the accounts array is empty. * * @dev <h4>Postconditions:</h4> * 1. Accounts previously in the list are removed. * 2. A `RemovedAccountFromList` event is emitted for each account that is removed from the list. * * @param id The id of the list. * @param accounts The addresses of the accounts to remove. */ function removeAccountsFromWhitelist( uint120 id, address[] calldata accounts ) external override onlyListOwner(id) notZero(accounts.length) { List storage whitelist = whitelists[id]; address account; for (uint256 i = 0; i < accounts.length;) { account = accounts[i]; if (whitelist.enumerableAccounts.remove(account)) { emit RemovedAccountFromList(ListTypes.Whitelist, id, account); delete whitelist.nonEnumerableAccounts[account]; } unchecked { ++i; } } } /** * @notice Removes one or more codehashes from a blacklist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the codehashes array is empty. * * @dev <h4>Postconditions:</h4> * 1. Codehashes previously in the list are removed. * 2. A `RemovedCodeHashFromList` event is emitted for each codehash that is removed from the list. * * @param id The id of the list. * @param codehashes The codehashes to remove. */ function removeCodeHashesFromBlacklist( uint120 id, bytes32[] calldata codehashes ) external override onlyListOwner(id) notZero(codehashes.length) { List storage blacklist = blacklists[id]; bytes32 codehash; for (uint256 i = 0; i < codehashes.length;) { codehash = codehashes[i]; if (blacklist.enumerableCodehashes.remove(codehash)) { emit RemovedCodeHashFromList(ListTypes.Blacklist, id, codehash); delete blacklist.nonEnumerableCodehashes[codehash]; } unchecked { ++i; } } } /** * @notice Removes one or more codehashes from a whitelist. * * @dev Throws when the caller does not own the specified list. * @dev Throws when the codehashes array is empty. * * @dev <h4>Postconditions:</h4> * 1. Codehashes previously in the list are removed. * 2. A `RemovedCodeHashFromList` event is emitted for each codehash that is removed from the list. * * @param id The id of the list. * @param codehashes The codehashes to remove. */ function removeCodeHashesFromWhitelist( uint120 id, bytes32[] calldata codehashes ) external override onlyListOwner(id) notZero(codehashes.length) { List storage whitelist = whitelists[id]; bytes32 codehash; for (uint256 i = 0; i < codehashes.length;) { codehash = codehashes[i]; if (whitelist.enumerableCodehashes.remove(codehash)) { emit RemovedCodeHashFromList(ListTypes.Whitelist, id, codehash); delete whitelist.nonEnumerableCodehashes[codehash]; } unchecked { ++i; } } } /** * @notice Get blacklisted accounts by list id. * @param id The id of the list. * @return An array of blacklisted accounts. */ function getBlacklistedAccounts(uint120 id) public view override returns (address[] memory) { return blacklists[id].enumerableAccounts.values(); } /** * @notice Get whitelisted accounts by list id. * @param id The id of the list. * @return An array of whitelisted accounts. */ function getWhitelistedAccounts(uint120 id) public view override returns (address[] memory) { return whitelists[id].enumerableAccounts.values(); } /** * @notice Get blacklisted codehashes by list id. * @param id The id of the list. * @return An array of blacklisted codehashes. */ function getBlacklistedCodeHashes(uint120 id) public view override returns (bytes32[] memory) { return blacklists[id].enumerableCodehashes.values(); } /** * @notice Get whitelisted codehashes by list id. * @param id The id of the list. * @return An array of whitelisted codehashes. */ function getWhitelistedCodeHashes(uint120 id) public view override returns (bytes32[] memory) { return whitelists[id].enumerableCodehashes.values(); } /** * @notice Check if an account is blacklisted in a specified list. * @param id The id of the list. * @param account The address of the account to check. * @return True if the account is blacklisted in the specified list, false otherwise. */ function isAccountBlacklisted(uint120 id, address account) public view override returns (bool) { return blacklists[id].nonEnumerableAccounts[account]; } /** * @notice Check if an account is whitelisted in a specified list. * @param id The id of the list. * @param account The address of the account to check. * @return True if the account is whitelisted in the specified list, false otherwise. */ function isAccountWhitelisted(uint120 id, address account) public view override returns (bool) { return whitelists[id].nonEnumerableAccounts[account]; } /** * @notice Check if a codehash is blacklisted in a specified list. * @param id The id of the list. * @param codehash The codehash to check. * @return True if the codehash is blacklisted in the specified list, false otherwise. */ function isCodeHashBlacklisted(uint120 id, bytes32 codehash) public view override returns (bool) { return codehash == CODEHASH_ZERO ? false : blacklists[id].nonEnumerableCodehashes[codehash]; } /** * @notice Check if a codehash is whitelisted in a specified list. * @param id The id of the list. * @param codehash The codehash to check. * @return True if the codehash is whitelisted in the specified list, false otherwise. */ function isCodeHashWhitelisted(uint120 id, bytes32 codehash) public view override returns (bool) { return codehash == CODEHASH_ZERO ? false : whitelists[id].nonEnumerableCodehashes[codehash]; } /** * @notice Get blacklisted accounts by collection. * @param collection The address of the collection. * @return An array of blacklisted accounts. */ function getBlacklistedAccountsByCollection(address collection) external view override returns (address[] memory) { return getBlacklistedAccounts(collectionSecurityPolicies[collection].listId); } /** * @notice Get whitelisted accounts by collection. * @param collection The address of the collection. * @return An array of whitelisted accounts. */ function getWhitelistedAccountsByCollection(address collection) external view override returns (address[] memory) { return getWhitelistedAccounts(collectionSecurityPolicies[collection].listId); } /** * @notice Get blacklisted codehashes by collection. * @param collection The address of the collection. * @return An array of blacklisted codehashes. */ function getBlacklistedCodeHashesByCollection(address collection) external view override returns (bytes32[] memory) { return getBlacklistedCodeHashes(collectionSecurityPolicies[collection].listId); } /** * @notice Get whitelisted codehashes by collection. * @param collection The address of the collection. * @return An array of whitelisted codehashes. */ function getWhitelistedCodeHashesByCollection(address collection) external view override returns (bytes32[] memory) { return getWhitelistedCodeHashes(collectionSecurityPolicies[collection].listId); } /** * @notice Check if an account is blacklisted by a specified collection. * @param collection The address of the collection. * @param account The address of the account to check. * @return True if the account is blacklisted by the specified collection, false otherwise. */ function isAccountBlacklistedByCollection(address collection, address account) external view override returns (bool) { return isAccountBlacklisted(collectionSecurityPolicies[collection].listId, account); } /** * @notice Check if an account is whitelisted by a specified collection. * @param collection The address of the collection. * @param account The address of the account to check. * @return True if the account is whitelisted by the specified collection, false otherwise. */ function isAccountWhitelistedByCollection(address collection, address account) external view override returns (bool) { return isAccountWhitelisted(collectionSecurityPolicies[collection].listId, account); } /** * @notice Check if a codehash is blacklisted by a specified collection. * @param collection The address of the collection. * @param codehash The codehash to check. * @return True if the codehash is blacklisted by the specified collection, false otherwise. */ function isCodeHashBlacklistedByCollection(address collection, bytes32 codehash) external view override returns (bool) { return isCodeHashBlacklisted(collectionSecurityPolicies[collection].listId, codehash); } /** * @notice Check if a codehash is whitelisted by a specified collection. * @param collection The address of the collection. * @param codehash The codehash to check. * @return True if the codehash is whitelisted by the specified collection, false otherwise. */ function isCodeHashWhitelistedByCollection(address collection, bytes32 codehash) external view override returns (bool) { return isCodeHashWhitelisted(collectionSecurityPolicies[collection].listId, codehash); } /// @notice ERC-165 Interface Support function supportsInterface(bytes4 interfaceId) public view virtual override(EOARegistry, IERC165) returns (bool) { return interfaceId == type(ITransferValidator).interfaceId || interfaceId == type(ITransferSecurityRegistry).interfaceId || interfaceId == type(ITransferSecurityRegistryV2).interfaceId || interfaceId == type(ICreatorTokenTransferValidator).interfaceId || interfaceId == type(ICreatorTokenTransferValidatorV2).interfaceId || super.supportsInterface(interfaceId); } /*************************************************************************/ /* HELPERS */ /*************************************************************************/ /** * @notice Reverts the transaction if the caller is not the owner or assigned the default * @notice admin role of the contract at `tokenAddress`. * * @dev Throws when the caller is neither owner nor assigned the default admin role. * * @param tokenAddress The contract address of the token to check permissions for. */ function _requireCallerIsNFTOrContractOwnerOrAdmin(address tokenAddress) internal view { bool callerHasPermissions = false; if(_getCodeLengthAsm(tokenAddress) > 0) { callerHasPermissions = _msgSender() == tokenAddress; if(!callerHasPermissions) { try IOwnable(tokenAddress).owner() returns (address contractOwner) { callerHasPermissions = _msgSender() == contractOwner; } catch {} if(!callerHasPermissions) { try IAccessControl(tokenAddress).hasRole(DEFAULT_ACCESS_CONTROL_ADMIN_ROLE, _msgSender()) returns (bool callerIsContractAdmin) { callerHasPermissions = callerIsContractAdmin; } catch {} } } } if(!callerHasPermissions) { revert CreatorTokenTransferValidator__CallerMustHaveElevatedPermissionsForSpecifiedNFT(); } } /** * @notice Copies all addresses in `ptrFromList` to `ptrToList`. * * @dev This function will copy all addresses from one list to another list. * @dev Note: If used to copy adddresses to an existing list the current list contents will not be * @dev deleted before copying. New addresses will be appeneded to the end of the list and the * @dev non-enumerable mapping key value will be set to true. * * @dev <h4>Postconditions:</h4> * 1. Addresses in from list that are not already present in to list are added to the to list. * 2. Emits an `AddedAccountToList` event for each address copied to the list. * * @param listType The type of list addresses are being copied from and to. * @param destinationListId The id of the list being copied to. * @param ptrFromList The storage pointer for the list being copied from. * @param ptrToList The storage pointer for the list being copied to. */ function _copyAddressSet( ListTypes listType, uint120 destinationListId, List storage ptrFromList, List storage ptrToList ) private { EnumerableSet.AddressSet storage ptrFromSet = ptrFromList.enumerableAccounts; EnumerableSet.AddressSet storage ptrToSet = ptrToList.enumerableAccounts; mapping (address => bool) storage ptrToNonEnumerableSet = ptrToList.nonEnumerableAccounts; uint256 sourceLength = ptrFromSet.length(); address account; for (uint256 i = 0; i < sourceLength;) { account = ptrFromSet.at(i); if (ptrToSet.add(account)) { emit AddedAccountToList(listType, destinationListId, account); ptrToNonEnumerableSet[account] = true; } unchecked { ++i; } } } /** * @notice Copies all codehashes in `ptrFromList` to `ptrToList`. * * @dev This function will copy all codehashes from one list to another list. * @dev Note: If used to copy codehashes to an existing list the current list contents will not be * @dev deleted before copying. New codehashes will be appeneded to the end of the list and the * @dev non-enumerable mapping key value will be set to true. * * @dev <h4>Postconditions:</h4> * 1. Codehashes in from list that are not already present in to list are added to the to list. * 2. Emits an `AddedCodeHashToList` event for each codehash copied to the list. * * @param listType The type of list codehashes are being copied from and to. * @param destinationListId The id of the list being copied to. * @param ptrFromList The storage pointer for the list being copied from. * @param ptrToList The storage pointer for the list being copied to. */ function _copyBytes32Set( ListTypes listType, uint120 destinationListId, List storage ptrFromList, List storage ptrToList ) private { EnumerableSet.Bytes32Set storage ptrFromSet = ptrFromList.enumerableCodehashes; EnumerableSet.Bytes32Set storage ptrToSet = ptrToList.enumerableCodehashes; mapping (bytes32 => bool) storage ptrToNonEnumerableSet = ptrToList.nonEnumerableCodehashes; uint256 sourceLength = ptrFromSet.length(); bytes32 codehash; for (uint256 i = 0; i < sourceLength;) { codehash = ptrFromSet.at(i); if (ptrToSet.add(codehash)) { emit AddedCodeHashToList(listType, destinationListId, codehash); ptrToNonEnumerableSet[codehash] = true; } unchecked { ++i; } } } /** * @notice Sets the owner of list `id` to `newOwner`. * * @dev Throws when the caller is not the owner of the list. * * @dev <h4>Postconditions:</h4> * 1. The owner of list `id` is set to `newOwner`. * 2. Emits a `ReassignedListOwnership` event. */ function _reassignOwnershipOfList(uint120 id, address newOwner) private { _requireCallerOwnsList(id); listOwners[id] = newOwner; emit ReassignedListOwnership(id, newOwner); } /** * @notice Requires the caller to be the owner of list `id`. * * @dev Throws when the caller is not the owner of the list. */ function _requireCallerOwnsList(uint120 id) private view { if (_msgSender() != listOwners[id]) { revert CreatorTokenTransferValidator__CallerDoesNotOwnList(); } } /** * @dev Internal function used to efficiently retrieve the code length of `account`. * * @param account The address to get the deployed code length for. * * @return length The length of deployed code at the address. */ function _getCodeLengthAsm(address account) internal view returns (uint256 length) { assembly { length := extcodesize(account) } } /** * @dev Internal function used to efficiently retrieve the codehash of `account`. * * @param account The address to get the deployed codehash for. * * @return codehash The codehash of the deployed code at the address. */ function _getCodeHashAsm(address account) internal view returns (bytes32 codehash) { assembly { codehash := extcodehash(account) } } /*************************************************************************/ /* BACKWARDS COMPATIBILITY */ /*************************************************************************/ /** * @notice Maps to `createList` in V2. */ function createOperatorWhitelist(string calldata name) external override returns (uint120) { return createList(name); } /** * @notice Maps to `reassignOwnershipOfList` in V2. */ function reassignOwnershipOfOperatorWhitelist(uint120 id, address newOwner) external override { reassignOwnershipOfList(id, newOwner); } /** * @notice Maps to `renounceOwnershipOfList` in V2. */ function renounceOwnershipOfOperatorWhitelist(uint120 id) external override { renounceOwnershipOfList(id); } /** * @notice Maps to `applyListToCollection` in V2. */ function setOperatorWhitelistOfCollection(address collection, uint120 id) external override { applyListToCollection(collection, id); } /** * @notice Adds a single account to the specified whitelist. * @dev Throws when the caller does not own the specified list. */ function addOperatorToWhitelist(uint120 id, address operator) external override onlyListOwner(id) { List storage whitelist = whitelists[id]; if (whitelist.enumerableAccounts.add(operator)) { emit AddedAccountToList(ListTypes.Whitelist, id, operator); whitelist.nonEnumerableAccounts[operator] = true; } } /** * @notice Removes a single account from the specified whitelist. * @dev Throws when the caller does not own the specified list. */ function removeOperatorFromWhitelist(uint120 id, address operator) external override onlyListOwner(id) { List storage whitelist = whitelists[id]; if (whitelist.enumerableAccounts.remove(operator)) { emit RemovedAccountFromList(ListTypes.Whitelist, id, operator); delete whitelist.nonEnumerableAccounts[operator]; } } /** * @notice Gets the V1 Collection Security Policy information. * Assigns both operatorWhitelistId and permittedContractReceiversId to the listId. */ function getCollectionSecurityPolicy(address collection) external view override returns (CollectionSecurityPolicy memory) { CollectionSecurityPolicyV2 memory collectionSecurityPolicy = collectionSecurityPolicies[collection]; return CollectionSecurityPolicy({ transferSecurityLevel: collectionSecurityPolicy.transferSecurityLevel, operatorWhitelistId: collectionSecurityPolicy.listId, permittedContractReceiversId: collectionSecurityPolicy.listId }); } /** * @notice Maps to `getWhitelistedAccounts` in V2. */ function getWhitelistedOperators(uint120 id) external view override returns (address[] memory) { return getWhitelistedAccounts(id); } /** * @notice Maps to `getWhitelistedAccounts` in V2. */ function getPermittedContractReceivers(uint120 id) external view override returns (address[] memory) { return getWhitelistedAccounts(id); } /** * @notice Maps to `isAccountWhitelisted` in V2. */ function isOperatorWhitelisted(uint120 id, address operator) external view override returns (bool) { return isAccountWhitelisted(id, operator); } /** * @notice Maps to `isAccountWhitelisted` in V2. */ function isContractReceiverPermitted(uint120 id, address receiver) external view override returns (bool) { return isAccountWhitelisted(id, receiver); } /** * @notice NO-OP Because V2 Allows Whitelisted Accounts To Be Contract Receivers Automatically. * @return 0 */ function createPermittedContractReceiverAllowlist(string calldata /*name*/) external pure override returns (uint120) { return 0; } /** * @notice NO-OP Because V2 Allows Whitelisted Accounts To Be Contract Receivers Automatically. */ function reassignOwnershipOfPermittedContractReceiverAllowlist( uint120 /*id*/, address /*newOwner*/ ) external pure override {} /** * @notice NO-OP Because V2 Allows Whitelisted Accounts To Be Contract Receivers Automatically. */ function renounceOwnershipOfPermittedContractReceiverAllowlist(uint120 /*id*/) external pure override {} /** * @notice NO-OP Because V2 Allows Whitelisted Accounts To Be Contract Receivers Automatically. */ function setPermittedContractReceiverAllowlistOfCollection( address /*collection*/, uint120 /*id*/ ) external pure override {} /** * @notice NO-OP Because V2 Allows Whitelisted Accounts To Be Contract Receivers Automatically. */ function addPermittedContractReceiverToAllowlist(uint120 /*id*/, address /*receiver*/) external pure override {} /** * @notice NO-OP Because V2 Allows Whitelisted Accounts To Be Contract Receivers Automatically. */ function removePermittedContractReceiverFromAllowlist( uint120 /*id*/, address /*receiver*/ ) external pure override {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../interfaces/IEOARegistry.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /// @dev Thrown when the caller does not match the recovered address for the signature. error CallerDidNotSignTheMessage(); /// @dev Thrown when the caller has already been verified. error SignatureAlreadyVerified(); /** * @title EOARegistry * @author Limit Break, Inc. * @notice A registry that may be used globally by any smart contract that limits contract interactions to verified EOA addresses only. * @dev Take care and carefully consider whether or not to use this. Restricting operations to EOA only accounts can break Defi composability, * so if Defi composability is an objective, this is not a good option. Be advised that in the future, EOA accounts might not be a thing * but this is yet to be determined. See https://eips.ethereum.org/EIPS/eip-4337 for more information. */ contract EOARegistry is Context, ERC165, IEOARegistry { /// @dev A pre-cached signed message hash used for gas-efficient signature recovery bytes32 immutable private signedMessageHash; /// @dev The plain text message to sign for signature verification string constant public MESSAGE_TO_SIGN = "EOA"; /// @dev Mapping of accounts that to signature verification status mapping (address => bool) private eoaSignatureVerified; /// @dev Emitted whenever a user verifies that they are an EOA by submitting their signature. event VerifiedEOASignature(address indexed account); constructor() { signedMessageHash = ECDSA.toEthSignedMessageHash(bytes(MESSAGE_TO_SIGN)); } /// @notice Allows a user to verify an ECDSA signature to definitively prove they are an EOA account. /// /// Throws when the caller has already verified their signature. /// Throws when the caller did not sign the message. /// /// Postconditions: /// --------------- /// The verified signature mapping has been updated to `true` for the caller. function verifySignature(bytes calldata signature) external { if(eoaSignatureVerified[_msgSender()]) { revert SignatureAlreadyVerified(); } if(_msgSender() != ECDSA.recover(signedMessageHash, signature)) { revert CallerDidNotSignTheMessage(); } eoaSignatureVerified[_msgSender()] = true; emit VerifiedEOASignature(_msgSender()); } /// @notice Allows a user to verify an ECDSA signature to definitively prove they are an EOA account. /// This version is passed the v, r, s components of the signature, and is slightly more gas efficient than /// calculating the v, r, s components on-chain. /// /// Throws when the caller has already verified their signature. /// Throws when the caller did not sign the message. /// /// Postconditions: /// --------------- /// The verified signature mapping has been updated to `true` for the caller. function verifySignatureVRS(uint8 v, bytes32 r, bytes32 s) external { if(eoaSignatureVerified[msg.sender]) { revert SignatureAlreadyVerified(); } if(msg.sender != ECDSA.recover(signedMessageHash, v, r, s)) { revert CallerDidNotSignTheMessage(); } eoaSignatureVerified[msg.sender] = true; emit VerifiedEOASignature(msg.sender); } /// @notice Returns true if the specified account has verified a signature on this registry, false otherwise. function isVerifiedEOA(address account) public view override returns (bool) { return eoaSignatureVerified[account]; } /// @dev ERC-165 interface support function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IEOARegistry).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; interface IOwnable { function owner() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IEOARegistry.sol"; import "./ITransferSecurityRegistry.sol"; import "./ITransferValidator.sol"; interface ICreatorTokenTransferValidator is ITransferSecurityRegistry, ITransferValidator, IEOARegistry {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IEOARegistry.sol"; import "./ITransferSecurityRegistryV2.sol"; import "./ITransferValidator.sol"; interface ICreatorTokenTransferValidatorV2 is ITransferSecurityRegistryV2, ITransferValidator, IEOARegistry {}
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ 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); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * 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; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; interface IEOARegistry is IERC165 { function isVerifiedEOA(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../utils/TransferPolicy.sol"; interface ITransferSecurityRegistry { event AddedToAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account); event CreatedAllowlist(AllowlistTypes indexed kind, uint256 indexed id, string indexed name); event ReassignedAllowlistOwnership(AllowlistTypes indexed kind, uint256 indexed id, address indexed newOwner); event RemovedFromAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account); event SetAllowlist(AllowlistTypes indexed kind, address indexed collection, uint120 indexed id); event SetTransferSecurityLevel(address indexed collection, TransferSecurityLevels level); function createOperatorWhitelist(string calldata name) external returns (uint120); function createPermittedContractReceiverAllowlist(string calldata name) external returns (uint120); function reassignOwnershipOfOperatorWhitelist(uint120 id, address newOwner) external; function reassignOwnershipOfPermittedContractReceiverAllowlist(uint120 id, address newOwner) external; function renounceOwnershipOfOperatorWhitelist(uint120 id) external; function renounceOwnershipOfPermittedContractReceiverAllowlist(uint120 id) external; function setTransferSecurityLevelOfCollection(address collection, TransferSecurityLevels level) external; function setOperatorWhitelistOfCollection(address collection, uint120 id) external; function setPermittedContractReceiverAllowlistOfCollection(address collection, uint120 id) external; function addOperatorToWhitelist(uint120 id, address operator) external; function addPermittedContractReceiverToAllowlist(uint120 id, address receiver) external; function removeOperatorFromWhitelist(uint120 id, address operator) external; function removePermittedContractReceiverFromAllowlist(uint120 id, address receiver) external; function getCollectionSecurityPolicy(address collection) external view returns (CollectionSecurityPolicy memory); function getWhitelistedOperators(uint120 id) external view returns (address[] memory); function getPermittedContractReceivers(uint120 id) external view returns (address[] memory); function isOperatorWhitelisted(uint120 id, address operator) external view returns (bool); function isContractReceiverPermitted(uint120 id, address receiver) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../utils/TransferPolicy.sol"; interface ITransferValidator { function applyCollectionTransferPolicy(address caller, address from, address to) external view; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./ITransferSecurityRegistry.sol"; interface ITransferSecurityRegistryV2 is ITransferSecurityRegistry { event CreatedList(uint256 indexed id, string name); event AppliedListToCollection(address indexed collection, uint120 indexed id); event ReassignedListOwnership(uint256 indexed id, address indexed newOwner); event AddedAccountToList(ListTypes indexed kind, uint256 indexed id, address indexed account); event AddedCodeHashToList(ListTypes indexed kind, uint256 indexed id, bytes32 indexed codehash); event RemovedAccountFromList(ListTypes indexed kind, uint256 indexed id, address indexed account); event RemovedCodeHashFromList(ListTypes indexed kind, uint256 indexed id, bytes32 indexed codehash); function transferSecurityPolicies(TransferSecurityLevels level) external pure returns (CallerConstraints callerConstraints, ReceiverConstraints receiverConstraints); function createList(string calldata name) external returns (uint120); function createListCopy(string calldata name, uint120 sourceListId) external returns (uint120); function reassignOwnershipOfList(uint120 id, address newOwner) external; function renounceOwnershipOfList(uint120 id) external; function applyListToCollection(address collection, uint120 id) external; function getCollectionSecurityPolicyV2(address collection) external view returns (CollectionSecurityPolicyV2 memory); function addAccountsToBlacklist(uint120 id, address[] calldata accounts) external; function addAccountsToWhitelist(uint120 id, address[] calldata accounts) external; function addCodeHashesToBlacklist(uint120 id, bytes32[] calldata codehashes) external; function addCodeHashesToWhitelist(uint120 id, bytes32[] calldata codehashes) external; function removeAccountsFromBlacklist(uint120 id, address[] calldata accounts) external; function removeAccountsFromWhitelist(uint120 id, address[] calldata accounts) external; function removeCodeHashesFromBlacklist(uint120 id, bytes32[] calldata codehashes) external; function removeCodeHashesFromWhitelist(uint120 id, bytes32[] calldata codehashes) external; function getBlacklistedAccounts(uint120 id) external view returns (address[] memory); function getWhitelistedAccounts(uint120 id) external view returns (address[] memory); function getBlacklistedCodeHashes(uint120 id) external view returns (bytes32[] memory); function getWhitelistedCodeHashes(uint120 id) external view returns (bytes32[] memory); function isAccountBlacklisted(uint120 id, address account) external view returns (bool); function isAccountWhitelisted(uint120 id, address account) external view returns (bool); function isCodeHashBlacklisted(uint120 id, bytes32 codehash) external view returns (bool); function isCodeHashWhitelisted(uint120 id, bytes32 codehash) external view returns (bool); function getBlacklistedAccountsByCollection(address collection) external view returns (address[] memory); function getWhitelistedAccountsByCollection(address collection) external view returns (address[] memory); function getBlacklistedCodeHashesByCollection(address collection) external view returns (bytes32[] memory); function getWhitelistedCodeHashesByCollection(address collection) external view returns (bytes32[] memory); function isAccountBlacklistedByCollection(address collection, address account) external view returns (bool); function isAccountWhitelistedByCollection(address collection, address account) external view returns (bool); function isCodeHashBlacklistedByCollection(address collection, bytes32 codehash) external view returns (bool); function isCodeHashWhitelistedByCollection(address collection, bytes32 codehash) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** * @dev Used in events to indicate the list type that an account or * @dev codehash is being added to or removed from. * * @dev Used in Creator Token Standards V2. */ enum ListTypes { // 0: List type that will block a matching address/codehash that is on the list. Blacklist, // 1: List type that will block any matching address/codehash that is not on the list. Whitelist } /** * @dev Used in events to indicate the list type that event relates to. * * @dev Used in Creator Token Standards V1. */ enum AllowlistTypes { // 0: List type that defines the allowed operator addresses. Operators, // 1: List type that defines the allowed contract receivers. PermittedContractReceivers } /** @dev Defines the constraints that will be applied for receipt of tokens. */ enum ReceiverConstraints { // 0: Any address may receive tokens. None, // 1: Address must not have deployed bytecode. NoCode, // 2: Address must verify a signature with the EOA Registry to prove it is an EOA. EOA } /** * @dev Defines the constraints that will be applied to the transfer caller. */ enum CallerConstraints { // 0: Any address may transfer tokens. None, // 1: Addresses and codehashes not on the blacklist may transfer tokens. OperatorBlacklistEnableOTC, // 2: Addresses and codehashes on the whitelist and the owner of the token may transfer tokens. OperatorWhitelistEnableOTC, // 3: Addresses and codehashes on the whitelist may transfer tokens. OperatorWhitelistDisableOTC } /** * @dev Defines constraints for staking tokens in token wrapper contracts. */ enum StakerConstraints { // 0: No constraints applied to staker. None, // 1: Transaction originator must be the address that will receive the wrapped tokens. CallerIsTxOrigin, // 2: Address that will receive the wrapped tokens must be a verified EOA. EOA } /** * @dev Used in both Creator Token Standards V1 and V2. * @dev Levels may have different transfer restrictions in V1 and V2. Refer to the * @dev Creator Token Transfer Validator implementation for the version being utilized * @dev to determine the effect of the selected level. */ enum TransferSecurityLevels { Recommended, One, Two, Three, Four, Five, Six, Seven, Eight } /** * @dev Defines the caller and receiver constraints for a transfer security level. * @dev Used in Creator Token Standards V1. * * @dev **callerConstraints**: The restrictions applied to the transfer caller. * @dev **receiverConstraints**: The restrictions applied to the transfer recipient. */ struct TransferSecurityPolicy { CallerConstraints callerConstraints; ReceiverConstraints receiverConstraints; } /** * @dev Defines the security policy for a token collection in Creator Token Standards V1. * * @dev **transferSecurityLevel**: The transfer security level set for the collection. * @dev **operatorWhitelistId**: The list id for the operator whitelist. * @dev **permittedContractReceiversId: The list id for the contracts that are allowed to receive tokens. */ struct CollectionSecurityPolicy { TransferSecurityLevels transferSecurityLevel; uint120 operatorWhitelistId; uint120 permittedContractReceiversId; } /** * @dev Defines the security policy for a token collection in Creator Token Standards V2. * * @dev **transferSecurityLevel**: The transfer security level set for the collection. * @dev **listId**: The list id that contains the blacklist and whitelist to apply to the collection. */ struct CollectionSecurityPolicyV2 { TransferSecurityLevels transferSecurityLevel; uint120 listId; } /** * @dev Used internally in the Creator Token Base V2 contract to pack transfer validator configuration. * * @dev **isInitialized**: If not initialized by the collection owner or admin the default validator will be used. * @dev **version**: The transfer validator version. * @dev **transferValidator**: The address of the transfer validator to use for applying collection security settings. */ struct TransferValidatorReference { bool isInitialized; uint16 version; address transferValidator; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
{ "remappings": [ "@openzeppelin/=lib/openzeppelin-contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "murky/=lib/murky/src/", "erc721a/=lib/ERC721A/", "@rari-capital/solmate/=lib/PermitC/lib/solmate/", "ERC721A/=lib/ERC721A/contracts/", "PermitC/=lib/PermitC/", "erc4626-tests/=lib/PermitC/lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-gas-metering/=lib/PermitC/lib/forge-gas-metering/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/PermitC/lib/openzeppelin-contracts/contracts/", "solady/=lib/PermitC/lib/forge-gas-metering/lib/solady/", "solmate/=lib/PermitC/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"defaultOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerDidNotSignTheMessage","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ArrayLengthCannotBeZero","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__CallerDoesNotOwnList","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__CallerMustBeWhitelisted","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__CallerMustHaveElevatedPermissionsForSpecifiedNFT","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ListDoesNotExist","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ListOwnershipCannotBeTransferredToZeroAddress","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__OperatorIsBlacklisted","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ReceiverMustNotHaveDeployedCode","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ReceiverProofOfEOASignatureUnverified","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ZeroAddressNotAllowed","type":"error"},{"inputs":[],"name":"CreatorTokenTransferValidator__ZeroCodeHashNotAllowed","type":"error"},{"inputs":[],"name":"SignatureAlreadyVerified","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ListTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AddedAccountToList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ListTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"codehash","type":"bytes32"}],"name":"AddedCodeHashToList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum AllowlistTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AddedToAllowlist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint120","name":"id","type":"uint120"}],"name":"AppliedListToCollection","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum AllowlistTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"string","name":"name","type":"string"}],"name":"CreatedAllowlist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"CreatedList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum AllowlistTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"ReassignedAllowlistOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"ReassignedListOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ListTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RemovedAccountFromList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ListTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"codehash","type":"bytes32"}],"name":"RemovedCodeHashFromList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum AllowlistTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RemovedFromAllowlist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum AllowlistTypes","name":"kind","type":"uint8"},{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint120","name":"id","type":"uint120"}],"name":"SetAllowlist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"}],"name":"SetTransferSecurityLevel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"VerifiedEOASignature","type":"event"},{"inputs":[],"name":"MESSAGE_TO_SIGN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"addAccountsToBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"addAccountsToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"bytes32[]","name":"codehashes","type":"bytes32[]"}],"name":"addCodeHashesToBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"bytes32[]","name":"codehashes","type":"bytes32[]"}],"name":"addCodeHashesToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"operator","type":"address"}],"name":"addOperatorToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"","type":"uint120"},{"internalType":"address","name":"","type":"address"}],"name":"addPermittedContractReceiverToAllowlist","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"applyCollectionTransferPolicy","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint120","name":"id","type":"uint120"}],"name":"applyListToCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"createList","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint120","name":"sourceListId","type":"uint120"}],"name":"createListCopy","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"createOperatorWhitelist","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"createPermittedContractReceiverAllowlist","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"getBlacklistedAccounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getBlacklistedAccountsByCollection","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"getBlacklistedCodeHashes","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getBlacklistedCodeHashesByCollection","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getCollectionSecurityPolicy","outputs":[{"components":[{"internalType":"enum TransferSecurityLevels","name":"transferSecurityLevel","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversId","type":"uint120"}],"internalType":"struct CollectionSecurityPolicy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getCollectionSecurityPolicyV2","outputs":[{"components":[{"internalType":"enum TransferSecurityLevels","name":"transferSecurityLevel","type":"uint8"},{"internalType":"uint120","name":"listId","type":"uint120"}],"internalType":"struct CollectionSecurityPolicyV2","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"getPermittedContractReceivers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"getWhitelistedAccounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getWhitelistedAccountsByCollection","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"getWhitelistedCodeHashes","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getWhitelistedCodeHashesByCollection","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"getWhitelistedOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"isAccountBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"isAccountBlacklistedByCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"isAccountWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"isAccountWhitelistedByCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"bytes32","name":"codehash","type":"bytes32"}],"name":"isCodeHashBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"bytes32","name":"codehash","type":"bytes32"}],"name":"isCodeHashBlacklistedByCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"bytes32","name":"codehash","type":"bytes32"}],"name":"isCodeHashWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"bytes32","name":"codehash","type":"bytes32"}],"name":"isCodeHashWhitelistedByCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"receiver","type":"address"}],"name":"isContractReceiverPermitted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isVerifiedEOA","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastListId","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"","type":"uint120"}],"name":"listOwners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"reassignOwnershipOfList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"reassignOwnershipOfOperatorWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"","type":"uint120"},{"internalType":"address","name":"","type":"address"}],"name":"reassignOwnershipOfPermittedContractReceiverAllowlist","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"removeAccountsFromBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"removeAccountsFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"bytes32[]","name":"codehashes","type":"bytes32[]"}],"name":"removeCodeHashesFromBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"bytes32[]","name":"codehashes","type":"bytes32[]"}],"name":"removeCodeHashesFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"operator","type":"address"}],"name":"removeOperatorFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"","type":"uint120"},{"internalType":"address","name":"","type":"address"}],"name":"removePermittedContractReceiverFromAllowlist","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"renounceOwnershipOfList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"}],"name":"renounceOwnershipOfOperatorWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"","type":"uint120"}],"name":"renounceOwnershipOfPermittedContractReceiverAllowlist","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint120","name":"id","type":"uint120"}],"name":"setOperatorWhitelistOfCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint120","name":"","type":"uint120"}],"name":"setPermittedContractReceiverAllowlistOfCollection","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"}],"name":"setTransferSecurityLevelOfCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"}],"name":"transferSecurityPolicies","outputs":[{"internalType":"enum CallerConstraints","name":"callerConstraints","type":"uint8"},{"internalType":"enum ReceiverConstraints","name":"receiverConstraints","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"verifySignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"verifySignatureVRS","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620040d6380380620040d683398101604081905262000034916200030b565b604080518082019091526003815262454f4160e81b6020820152620000599062000143565b608052600080805260026020527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b80546001600160a01b0384166001600160a01b031990911617905560405181907f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be1490620000f4906020808252600c908201526b1111519055531508131254d560a21b604082015260600190565b60405180910390a26040516001600160a01b038316906001600160781b038316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736790600090a35050620003d8565b60006200015782516200018860201b60201c565b826040516020016200016b92919062000363565b604051602081830303815290604052805190602001209050919050565b60606000620001978362000221565b60010190506000816001600160401b03811115620001b957620001b9620003c2565b6040519080825280601f01601f191660200182016040528015620001e4576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084620001ee57509392505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106200026b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831062000298576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310620002b757662386f26fc10000830492506010015b6305f5e1008310620002d0576305f5e100830492506008015b6127108310620002e557612710830492506004015b60648310620002f8576064830492506002015b600a831062000305576001015b92915050565b6000602082840312156200031e57600080fd5b81516001600160a01b03811681146200033657600080fd5b9392505050565b60005b838110156200035a57818101518382015260200162000340565b50506000910152565b7f19457468657265756d205369676e6564204d6573736167653a0a0000000000008152600083516200039d81601a8501602088016200033d565b835190830190620003b681601a8401602088016200033d565b01601a01949350505050565b634e487b7160e01b600052604160045260246000fd5b608051613cdb620003fb60003960008181611b5301526128960152613cdb6000f3fe608060405234801561001057600080fd5b50600436106103835760003560e01c80637f39e7e4116101de578063ae602f441161010f578063d72dde5e116100ad578063e30cd5e11161007c578063e30cd5e1146104e2578063e991dc30146108ef578063f80af98414610902578063fec1d6431461091557600080fd5b8063d72dde5e14610748578063da0194c0146108b6578063de02cbb1146108c9578063def0125b146108dc57600080fd5b8063b8dcc68f116100e9578063b8dcc68f1461085d578063b955455214610870578063bf7bfd7e14610890578063d415f62f146108a357600080fd5b8063ae602f44146107d9578063b6567f2214610834578063b67d8f991461084a57600080fd5b80639445f5301161017c5780639e814cae116101565780639e814cae14610781578063a1cc5cc1146107a2578063a5d56b46146107b5578063a9f138eb146107c857600080fd5b80639445f53014610748578063982d03c01461075b57806399f9a6781461076e57600080fd5b80638b6ee865116101b85780638b6ee865146107015780638d744314146107145780638e28800f146107225780639340a7cc1461073557600080fd5b80637f39e7e41461069557806389631626146106b557806389a9c855146106c857600080fd5b806333f0901b116102b8578063515f7b28116102565780636bfab91d116102305780636bfab91d146106495780637161ac8d1461065c578063731fb9d81461066f5780637bac97de1461068257600080fd5b8063515f7b28146106105780635e17263d14610623578063697108281461063657600080fd5b80633fe5df99116102925780633fe5df99146104cf578063409dc573146105d75780634c9d0b45146105ea578063501b7d2e146105fd57600080fd5b806333f0901b1461057b57806334778f6a146105c4578063372fb54d146104e257600080fd5b806317e94a6c1161032557806323c99262116102ff57806323c9926214610507578063285fb8c8146105425780632c7fe70a146105555780632eb0b98a1461056857600080fd5b806317e94a6c146104cf57806318fbf6fe146104e25780632304aa02146104f457600080fd5b806310b5c6a01161036157806310b5c6a0146104215780631390a2c21461044157806316a17ce01461045457806316f18d74146104af57600080fd5b8063015499301461038857806301ffc9a71461039d578063057497cb146103c5575b600080fd5b61039b6103963660046135dd565b610928565b005b6103b06103ab366004613630565b610ad5565b60405190151581526020015b60405180910390f35b6103b06103d3366004613694565b6effffffffffffffffffffffffffffff8216600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260040190915290205460ff1692915050565b61043461042f3660046136cb565b610c1f565b6040516103bc91906136e6565b61039b61044f366004613694565b610c4b565b6103b0610462366004613694565b6effffffffffffffffffffffffffffff8216600090815260046020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205460ff1692915050565b6104c26104bd366004613740565b610d2c565b6040516103bc919061375d565b6104346104dd3660046136cb565b610d74565b61039b6104f0366004613694565b5050565b61039b610502366004613795565b610d7f565b600154610522906effffffffffffffffffffffffffffff1681565b6040516effffffffffffffffffffffffffffff90911681526020016103bc565b61039b6105503660046137ca565b610d89565b6103b0610563366004613815565b611212565b61039b6105763660046135dd565b61125f565b6105b76040518060400160405280600381526020017f454f41000000000000000000000000000000000000000000000000000000000081525081565b6040516103bc9190613841565b61039b6105d23660046136cb565b6113b2565b61039b6105e53660046135dd565b6113bb565b6104c26105f83660046136cb565b611513565b61052261060b3660046138ef565b611542565b61039b61061e3660046135dd565b61154e565b6103b0610631366004613931565b611672565b61039b6106443660046135dd565b6116b9565b61039b610657366004613694565b61180c565b6104c261066a3660046136cb565b611863565b61039b61067d366004613694565b611892565b6103b061069036600461394d565b61189c565b6106a86106a3366004613740565b6118fd565b6040516103bc91906139ae565b6104346106c33660046136cb565b61198f565b6103b06106d6366004613740565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b61039b61070f3660046136cb565b6119bb565b61039b6104f0366004613795565b6103b061073036600461394d565b6119c6565b6104c2610743366004613740565b611a27565b6103b0610756366004613694565b611a6f565b610434610769366004613740565b611abc565b61039b61077c3660046139e0565b611b04565b61079461078f366004613a2a565b611c41565b6040516103bc929190613a45565b61039b6107b03660046135dd565b611d75565b61039b6107c33660046135dd565b611f18565b61039b6107d63660046136cb565b50565b61080f6107e73660046136cb565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103bc565b6105226108423660046138ef565b600092915050565b6103b0610858366004613815565b612070565b61052261086b3660046138ef565b6120b6565b61088361087e366004613740565b6121fb565b6040516103bc9190613a79565b61039b61089e366004613795565b6122f4565b6103b06108b1366004613931565b6123e3565b61039b6108c4366004613abd565b612422565b6105226108d7366004613ae9565b6124e2565b61039b6108ea3660046135dd565b6126db565b6104346108fd366004613740565b6127ff565b61039b6109103660046138ef565b612847565b61039b610923366004613694565b6129b7565b8261093281612a9a565b81600081900361096e576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb578686828181106109ab576109ab613b3d565b90506020020160208101906109c09190613740565b915073ffffffffffffffffffffffffffffffffffffffff8216610a0f576040517f64019f1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a198383612b1f565b15610ac35773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660006040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101610991565b5050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f285fb8c8000000000000000000000000000000000000000000000000000000001480610b6857507fffffffff0000000000000000000000000000000000000000000000000000000082167f8f1d689900000000000000000000000000000000000000000000000000000000145b80610bb457507fffffffff0000000000000000000000000000000000000000000000000000000082167ff3417f1a00000000000000000000000000000000000000000000000000000000145b80610bdf57507fffffffff000000000000000000000000000000000000000000000000000000008216155b80610c0a57507fffffffff000000000000000000000000000000000000000000000000000000008216155b80610c195750610c1982612b41565b92915050565b6effffffffffffffffffffffffffffff81166000908152600460205260409020606090610c1990612bd8565b81610c5581612a9a565b6effffffffffffffffffffffffffffff83166000908152600560205260409020610c7f8184612be5565b15610d265773ffffffffffffffffffffffffffffffffffffffff83166effffffffffffffffffffffffffffff851660016040517f503012490a650739416858609e898957b874d17415a062945179c5735797884090600090a473ffffffffffffffffffffffffffffffffffffffff83166000908152600482016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff16611863565b6060610c198261198f565b6104f082826122f4565b3360009081526003602052604081208054909161010082046effffffffffffffffffffffffffffff16918190610dc19060ff16611c41565b6effffffffffffffffffffffffffffff8516600090815260056020526040902091935091506001826002811115610dfa57610dfa61396b565b03610e8657853b15610e815773ffffffffffffffffffffffffffffffffffffffff8616600090815260048201602052604090205460ff16610e8157853f600090815260058201602052604090205460ff16610e81576040517faca58aa000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f47565b6002826002811115610e9a57610e9a61396b565b03610f475773ffffffffffffffffffffffffffffffffffffffff861660009081526020819052604090205460ff16610f475773ffffffffffffffffffffffffffffffffffffffff8616600090815260048201602052604090205460ff16610f4757853f600090815260058201602052604090205460ff16610f47576040517fce32f2aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1603610f9d576003836003811115610f8e57610f8e61396b565b14610f9d575050505050505050565b6001836003811115610fb157610fb161396b565b03611089576effffffffffffffffffffffffffffff8416600090815260046020818152604080842073ffffffffffffffffffffffffffffffffffffffff8d1685529283019091529091205460ff1615611036576040517f409e6e1e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b883f600090815260058201602052604090205460ff1615611083576040517f409e6e1e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610acb565b600283600381111561109d5761109d61396b565b036111335773ffffffffffffffffffffffffffffffffffffffff8816600090815260048201602052604090205460ff16156110dc575050505050505050565b873f600090815260058201602052604090205460ff1615611101575050505050505050565b6040517fef28f90100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038360038111156111475761114761396b565b03610acb5773ffffffffffffffffffffffffffffffffffffffff8816600090815260048201602081905260409091205460ff161561118a57505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff881660009081526020829052604090205460ff16156111c357505050505050505050565b883f600090815260058301602081905260409091205460ff16156111ed5750505050505050505050565b883f60009081526020829052604090205460ff16156111015750505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120546112589061010090046effffffffffffffffffffffffffffff16836123e3565b9392505050565b8261126981612a9a565b8160008190036112a5576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb578686828181106112e2576112e2613b3d565b90506020020160208101906112f79190613740565b91506113038383612be5565b156113aa5773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660016040517f503012490a650739416858609e898957b874d17415a062945179c5735797884090600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b6001016112c8565b6107d6816119bb565b826113c581612a9a565b816000819003611401576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb5786868281811061143e5761143e613b3d565b60200291909101359250829050611481576040517f2bb30b6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148e6002840183612c07565b1561150b57816effffffffffffffffffffffffffffff891660016040517fc8615322788d404dfe307db9eef031bc148d1cec5e270a1fd6528a02b445d44590600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611424565b6effffffffffffffffffffffffffffff81166000908152600560205260409020606090610c1990600201612bd8565b600061125883836120b6565b8261155881612a9a565b816000819003611594576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb578686828181106115d1576115d1613b3d565b9050602002013591506115f08284600201612c1390919063ffffffff16565b1561166a57816effffffffffffffffffffffffffffff891660016040517f061d78094976b1d9ae7bb858f141c915b46152756409caadb07482983c2ca30190600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b6001016115b7565b600081156116b0576effffffffffffffffffffffffffffff83166000908152600560208181526040808420868552909201905290205460ff16611258565b50600092915050565b826116c381612a9a565b8160008190036116ff576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb5786868281811061173c5761173c613b3d565b90506020020160208101906117519190613740565b915061175d8383612be5565b156118045773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660006040517f503012490a650739416858609e898957b874d17415a062945179c5735797884090600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600101611722565b73ffffffffffffffffffffffffffffffffffffffff8116611859576040517f1f4ee59800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104f08282612c1f565b6effffffffffffffffffffffffffffff81166000908152600460205260409020606090610c1990600201612bd8565b6104f0828261180c565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526003602090815260408083205461010090046effffffffffffffffffffffffffffff168352600480835281842094861684529390930190529081205460ff16611258565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409081902081518083019092528054829060ff1660088111156119585761195861396b565b60088111156119695761196961396b565b8152905461010090046effffffffffffffffffffffffffffff1660209091015292915050565b6effffffffffffffffffffffffffffff81166000908152600560205260409020606090610c1990612bd8565b6107d6816000612c1f565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526003602090815260408083205461010090046effffffffffffffffffffffffffffff168352600582528083209385168352600490930190529081205460ff16611258565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff16611513565b6effffffffffffffffffffffffffffff8216600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260040190915281205460ff16611258565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff16610c1f565b3360009081526020819052604090205460ff1615611b4e576040517fce8c510800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7a7f0000000000000000000000000000000000000000000000000000000000000000848484612cb6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bde576040517f7640718d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fe7f8d62df5af850daa5d677e9e5c8065b7b549ec99ae61ba0ffaa9f5bf3e2d039190a2505050565b60008080836008811115611c5757611c5761396b565b03611c685750600290506000915091565b6001836008811115611c7c57611c7c61396b565b03611c8c57506000905080915091565b6002836008811115611ca057611ca061396b565b03611cb15750600190506000915091565b6003836008811115611cc557611cc561396b565b03611cd65750600290506000915091565b6004836008811115611cea57611cea61396b565b03611cfb5750600390506000915091565b6005836008811115611d0f57611d0f61396b565b03611d205750600290506001915091565b6006836008811115611d3457611d3461396b565b03611d4457506002905080915091565b6007836008811115611d5857611d5861396b565b03611d695750600390506001915091565b50600390506002915091565b82611d7f81612a9a565b816000819003611dbb576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb57868682818110611df857611df8613b3d565b9050602002016020810190611e0d9190613740565b915073ffffffffffffffffffffffffffffffffffffffff8216611e5c576040517f64019f1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e668383612b1f565b15611f105773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660016040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611dde565b82611f2281612a9a565b816000819003611f5e576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb57868682818110611f9b57611f9b613b3d565b60200291909101359250829050611fde576040517f2bb30b6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611feb6002840183612c07565b1561206857816effffffffffffffffffffffffffffff891660006040517fc8615322788d404dfe307db9eef031bc148d1cec5e270a1fd6528a02b445d44590600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611f81565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120546112589061010090046effffffffffffffffffffffffffffff1683611672565b60018054600091829182906120db906effffffffffffffffffffffffffffff16613b9b565b91906101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff160217905590506121173390565b6effffffffffffffffffffffffffffff82166000818152600260205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff949094169390931790925590517f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be14906121ae9087908790613bc9565b60405180910390a260405133906effffffffffffffffffffffffffffff8316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736790600090a39392505050565b604080516060810182526000808252602082018190529181019190915273ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604080822081518083019092528054829060ff16600881111561225e5761225e61396b565b600881111561226f5761226f61396b565b8152905461010090046effffffffffffffffffffffffffffff166020909101526040805160608101909152815191925090819060088111156122b3576122b361396b565b815260200182602001516effffffffffffffffffffffffffffff16815260200182602001516effffffffffffffffffffffffffffff16815250915050919050565b6122fd82612cde565b6001546effffffffffffffffffffffffffffff908116908216111561234e576040517ff716872600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602052604080822080547fffffffffffffffffffffffffffffffff000000000000000000000000000000ff166101006effffffffffffffffffffffffffffff87169081029190911790915590519092917fa66ff5557b7dc1562bb5e83306e15b513a25aa7537369bce38fc29c20847a79191a35050565b600081156116b0576effffffffffffffffffffffffffffff8316600090815260046020908152604080832085845260050190915290205460ff16611258565b61242b82612cde565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600881111561248b5761248b61396b565b02179055508173ffffffffffffffffffffffffffffffffffffffff167fb39d8f1e6f05413a407e46fc950eb92e9f5b3d65a47c3f0bdc7a2741a6ec0f7d826040516124d69190613c16565b60405180910390a25050565b6001805460009182918290612507906effffffffffffffffffffffffffffff16613b9b565b91906101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff16021790559050600181036effffffffffffffffffffffffffffff16836effffffffffffffffffffffffffffff16111561259b576040517ff716872600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff81166000818152600260205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055517f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be14906126159088908890613bc9565b60405180910390a260405133906effffffffffffffffffffffffffffff8316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736790600090a36effffffffffffffffffffffffffffff8084166000908152600460208181526040808420600580845282862096881686529383528185209390925283209093926126a790868685612eb7565b6126b46000868685612fb8565b6126c16001868584612eb7565b6126ce6001868584612fb8565b5092979650505050505050565b826126e581612a9a565b816000819003612721576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb5786868281811061275e5761275e613b3d565b90506020020135915061277d8284600201612c1390919063ffffffff16565b156127f757816effffffffffffffffffffffffffffff891660006040517f061d78094976b1d9ae7bb858f141c915b46152756409caadb07482983c2ca30190600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600101612744565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff1661198f565b3360009081526020819052604090205460ff1615612891576040517fce8c510800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128f17f000000000000000000000000000000000000000000000000000000000000000083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061308692505050565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612955576040517f7640718d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fe7f8d62df5af850daa5d677e9e5c8065b7b549ec99ae61ba0ffaa9f5bf3e2d039190a25050565b816129c181612a9a565b6effffffffffffffffffffffffffffff831660009081526005602052604090206129eb8184612b1f565b15610d265773ffffffffffffffffffffffffffffffffffffffff83166effffffffffffffffffffffffffffff851660016040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff83166000908152600482016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550505050565b6effffffffffffffffffffffffffffff811660009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107d6576040517f4e680cb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006112588373ffffffffffffffffffffffffffffffffffffffff84166130aa565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f89a9c855000000000000000000000000000000000000000000000000000000001480610c1957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610c19565b60606000611258836130f9565b60006112588373ffffffffffffffffffffffffffffffffffffffff8416613155565b600061125883836130aa565b60006112588383613155565b612c2882612a9a565b6effffffffffffffffffffffffffffff821660008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590519092917f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736791a35050565b6000806000612cc787878787613248565b91509150612cd481613337565b5095945050505050565b6000813b15612e8057503373ffffffffffffffffffffffffffffffffffffffff82161480612e80578173ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612d8b575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612d8891810190613c24565b60015b15612dab5773ffffffffffffffffffffffffffffffffffffffff16331490505b80612e805773ffffffffffffffffffffffffffffffffffffffff82166391d148546000336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925273ffffffffffffffffffffffffffffffffffffffff166024820152604401602060405180830381865afa925050508015612e78575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612e7591810190613c41565b60015b15612e805790505b806104f0576040517f7f954ba100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181600481016000612ec8846134ef565b90506000805b82811015612fac57612ee086826134f9565b9150612eec8583612b1f565b15612fa4578173ffffffffffffffffffffffffffffffffffffffff16896effffffffffffffffffffffffffffff168b6001811115612f2c57612f2c61396b565b6040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff8216600090815260208590526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101612ece565b50505050505050505050565b6002808301908201600583016000612fcf846134ef565b90506000805b82811015612fac57612fe786826134f9565b9150612ff38583612c07565b1561307e5781896effffffffffffffffffffffffffffff168b600181111561301d5761301d61396b565b6040517fc8615322788d404dfe307db9eef031bc148d1cec5e270a1fd6528a02b445d44590600090a4600082815260208590526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101612fd5565b60008060006130958585613505565b915091506130a281613337565b509392505050565b60008181526001830160205260408120546130f157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610c19565b506000610c19565b60608160000180548060200260200160405190810160405280929190818152602001828054801561314957602002820191906000526020600020905b815481526020019060010190808311613135575b50505050509050919050565b6000818152600183016020526040812054801561323e576000613179600183613c63565b855490915060009061318d90600190613c63565b90508181146131f25760008660000182815481106131ad576131ad613b3d565b90600052602060002001549050808760000184815481106131d0576131d0613b3d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061320357613203613c76565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610c19565b6000915050610c19565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561327f575060009050600361332e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156132d3573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166133275760006001925092505061332e565b9150600090505b94509492505050565b600081600481111561334b5761334b61396b565b036133535750565b60018160048111156133675761336761396b565b036133d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b60028160048111156133e7576133e761396b565b0361344e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016133ca565b60038160048111156134625761346261396b565b036107d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016133ca565b6000610c19825490565b6000611258838361354a565b600080825160410361353b5760208301516040840151606085015160001a61352f87828585613248565b94509450505050613543565b506000905060025b9250929050565b600082600001828154811061356157613561613b3d565b9060005260206000200154905092915050565b80356effffffffffffffffffffffffffffff8116811461359357600080fd5b919050565b60008083601f8401126135aa57600080fd5b50813567ffffffffffffffff8111156135c257600080fd5b6020830191508360208260051b850101111561354357600080fd5b6000806000604084860312156135f257600080fd5b6135fb84613574565b9250602084013567ffffffffffffffff81111561361757600080fd5b61362386828701613598565b9497909650939450505050565b60006020828403121561364257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461125857600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146107d657600080fd5b600080604083850312156136a757600080fd5b6136b083613574565b915060208301356136c081613672565b809150509250929050565b6000602082840312156136dd57600080fd5b61125882613574565b6020808252825182820181905260009190848201906040850190845b8181101561373457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613702565b50909695505050505050565b60006020828403121561375257600080fd5b813561125881613672565b6020808252825182820181905260009190848201906040850190845b8181101561373457835183529284019291840191600101613779565b600080604083850312156137a857600080fd5b82356137b381613672565b91506137c160208401613574565b90509250929050565b6000806000606084860312156137df57600080fd5b83356137ea81613672565b925060208401356137fa81613672565b9150604084013561380a81613672565b809150509250925092565b6000806040838503121561382857600080fd5b823561383381613672565b946020939093013593505050565b600060208083528351808285015260005b8181101561386e57858101830151858201604001528201613852565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008083601f8401126138bf57600080fd5b50813567ffffffffffffffff8111156138d757600080fd5b60208301915083602082850101111561354357600080fd5b6000806020838503121561390257600080fd5b823567ffffffffffffffff81111561391957600080fd5b613925858286016138ad565b90969095509350505050565b6000806040838503121561394457600080fd5b61383383613574565b6000806040838503121561396057600080fd5b82356136b081613672565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600981106139aa576139aa61396b565b9052565b60006040820190506139c182845161399a565b6020928301516effffffffffffffffffffffffffffff16919092015290565b6000806000606084860312156139f557600080fd5b833560ff81168114613a0657600080fd5b95602085013595506040909401359392505050565b80356009811061359357600080fd5b600060208284031215613a3c57600080fd5b61125882613a1b565b6040810160048410613a5957613a5961396b565b83825260038310613a6c57613a6c61396b565b8260208301529392505050565b6000606082019050613a8c82845161399a565b60208301516effffffffffffffffffffffffffffff8082166020850152806040860151166040850152505092915050565b60008060408385031215613ad057600080fd5b8235613adb81613672565b91506137c160208401613a1b565b600080600060408486031215613afe57600080fd5b833567ffffffffffffffff811115613b1557600080fd5b613b21868287016138ad565b9094509250613b34905060208501613574565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006effffffffffffffffffffffffffffff808316818103613bbf57613bbf613b6c565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60208101610c19828461399a565b600060208284031215613c3657600080fd5b815161125881613672565b600060208284031215613c5357600080fd5b8151801515811461125857600080fd5b81810381811115610c1957610c19613b6c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220b2e22ffac36fef1d4cc736309089b3d0e9c332fda01fd4faf1593371ad9d647a64736f6c6343000813003300000000000000000000000067985b1f8b613b57077bbdb24a5defcdda458317
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103835760003560e01c80637f39e7e4116101de578063ae602f441161010f578063d72dde5e116100ad578063e30cd5e11161007c578063e30cd5e1146104e2578063e991dc30146108ef578063f80af98414610902578063fec1d6431461091557600080fd5b8063d72dde5e14610748578063da0194c0146108b6578063de02cbb1146108c9578063def0125b146108dc57600080fd5b8063b8dcc68f116100e9578063b8dcc68f1461085d578063b955455214610870578063bf7bfd7e14610890578063d415f62f146108a357600080fd5b8063ae602f44146107d9578063b6567f2214610834578063b67d8f991461084a57600080fd5b80639445f5301161017c5780639e814cae116101565780639e814cae14610781578063a1cc5cc1146107a2578063a5d56b46146107b5578063a9f138eb146107c857600080fd5b80639445f53014610748578063982d03c01461075b57806399f9a6781461076e57600080fd5b80638b6ee865116101b85780638b6ee865146107015780638d744314146107145780638e28800f146107225780639340a7cc1461073557600080fd5b80637f39e7e41461069557806389631626146106b557806389a9c855146106c857600080fd5b806333f0901b116102b8578063515f7b28116102565780636bfab91d116102305780636bfab91d146106495780637161ac8d1461065c578063731fb9d81461066f5780637bac97de1461068257600080fd5b8063515f7b28146106105780635e17263d14610623578063697108281461063657600080fd5b80633fe5df99116102925780633fe5df99146104cf578063409dc573146105d75780634c9d0b45146105ea578063501b7d2e146105fd57600080fd5b806333f0901b1461057b57806334778f6a146105c4578063372fb54d146104e257600080fd5b806317e94a6c1161032557806323c99262116102ff57806323c9926214610507578063285fb8c8146105425780632c7fe70a146105555780632eb0b98a1461056857600080fd5b806317e94a6c146104cf57806318fbf6fe146104e25780632304aa02146104f457600080fd5b806310b5c6a01161036157806310b5c6a0146104215780631390a2c21461044157806316a17ce01461045457806316f18d74146104af57600080fd5b8063015499301461038857806301ffc9a71461039d578063057497cb146103c5575b600080fd5b61039b6103963660046135dd565b610928565b005b6103b06103ab366004613630565b610ad5565b60405190151581526020015b60405180910390f35b6103b06103d3366004613694565b6effffffffffffffffffffffffffffff8216600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260040190915290205460ff1692915050565b61043461042f3660046136cb565b610c1f565b6040516103bc91906136e6565b61039b61044f366004613694565b610c4b565b6103b0610462366004613694565b6effffffffffffffffffffffffffffff8216600090815260046020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205460ff1692915050565b6104c26104bd366004613740565b610d2c565b6040516103bc919061375d565b6104346104dd3660046136cb565b610d74565b61039b6104f0366004613694565b5050565b61039b610502366004613795565b610d7f565b600154610522906effffffffffffffffffffffffffffff1681565b6040516effffffffffffffffffffffffffffff90911681526020016103bc565b61039b6105503660046137ca565b610d89565b6103b0610563366004613815565b611212565b61039b6105763660046135dd565b61125f565b6105b76040518060400160405280600381526020017f454f41000000000000000000000000000000000000000000000000000000000081525081565b6040516103bc9190613841565b61039b6105d23660046136cb565b6113b2565b61039b6105e53660046135dd565b6113bb565b6104c26105f83660046136cb565b611513565b61052261060b3660046138ef565b611542565b61039b61061e3660046135dd565b61154e565b6103b0610631366004613931565b611672565b61039b6106443660046135dd565b6116b9565b61039b610657366004613694565b61180c565b6104c261066a3660046136cb565b611863565b61039b61067d366004613694565b611892565b6103b061069036600461394d565b61189c565b6106a86106a3366004613740565b6118fd565b6040516103bc91906139ae565b6104346106c33660046136cb565b61198f565b6103b06106d6366004613740565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b61039b61070f3660046136cb565b6119bb565b61039b6104f0366004613795565b6103b061073036600461394d565b6119c6565b6104c2610743366004613740565b611a27565b6103b0610756366004613694565b611a6f565b610434610769366004613740565b611abc565b61039b61077c3660046139e0565b611b04565b61079461078f366004613a2a565b611c41565b6040516103bc929190613a45565b61039b6107b03660046135dd565b611d75565b61039b6107c33660046135dd565b611f18565b61039b6107d63660046136cb565b50565b61080f6107e73660046136cb565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103bc565b6105226108423660046138ef565b600092915050565b6103b0610858366004613815565b612070565b61052261086b3660046138ef565b6120b6565b61088361087e366004613740565b6121fb565b6040516103bc9190613a79565b61039b61089e366004613795565b6122f4565b6103b06108b1366004613931565b6123e3565b61039b6108c4366004613abd565b612422565b6105226108d7366004613ae9565b6124e2565b61039b6108ea3660046135dd565b6126db565b6104346108fd366004613740565b6127ff565b61039b6109103660046138ef565b612847565b61039b610923366004613694565b6129b7565b8261093281612a9a565b81600081900361096e576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb578686828181106109ab576109ab613b3d565b90506020020160208101906109c09190613740565b915073ffffffffffffffffffffffffffffffffffffffff8216610a0f576040517f64019f1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a198383612b1f565b15610ac35773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660006040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101610991565b5050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f285fb8c8000000000000000000000000000000000000000000000000000000001480610b6857507fffffffff0000000000000000000000000000000000000000000000000000000082167f8f1d689900000000000000000000000000000000000000000000000000000000145b80610bb457507fffffffff0000000000000000000000000000000000000000000000000000000082167ff3417f1a00000000000000000000000000000000000000000000000000000000145b80610bdf57507fffffffff000000000000000000000000000000000000000000000000000000008216155b80610c0a57507fffffffff000000000000000000000000000000000000000000000000000000008216155b80610c195750610c1982612b41565b92915050565b6effffffffffffffffffffffffffffff81166000908152600460205260409020606090610c1990612bd8565b81610c5581612a9a565b6effffffffffffffffffffffffffffff83166000908152600560205260409020610c7f8184612be5565b15610d265773ffffffffffffffffffffffffffffffffffffffff83166effffffffffffffffffffffffffffff851660016040517f503012490a650739416858609e898957b874d17415a062945179c5735797884090600090a473ffffffffffffffffffffffffffffffffffffffff83166000908152600482016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff16611863565b6060610c198261198f565b6104f082826122f4565b3360009081526003602052604081208054909161010082046effffffffffffffffffffffffffffff16918190610dc19060ff16611c41565b6effffffffffffffffffffffffffffff8516600090815260056020526040902091935091506001826002811115610dfa57610dfa61396b565b03610e8657853b15610e815773ffffffffffffffffffffffffffffffffffffffff8616600090815260048201602052604090205460ff16610e8157853f600090815260058201602052604090205460ff16610e81576040517faca58aa000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f47565b6002826002811115610e9a57610e9a61396b565b03610f475773ffffffffffffffffffffffffffffffffffffffff861660009081526020819052604090205460ff16610f475773ffffffffffffffffffffffffffffffffffffffff8616600090815260048201602052604090205460ff16610f4757853f600090815260058201602052604090205460ff16610f47576040517fce32f2aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1603610f9d576003836003811115610f8e57610f8e61396b565b14610f9d575050505050505050565b6001836003811115610fb157610fb161396b565b03611089576effffffffffffffffffffffffffffff8416600090815260046020818152604080842073ffffffffffffffffffffffffffffffffffffffff8d1685529283019091529091205460ff1615611036576040517f409e6e1e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b883f600090815260058201602052604090205460ff1615611083576040517f409e6e1e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610acb565b600283600381111561109d5761109d61396b565b036111335773ffffffffffffffffffffffffffffffffffffffff8816600090815260048201602052604090205460ff16156110dc575050505050505050565b873f600090815260058201602052604090205460ff1615611101575050505050505050565b6040517fef28f90100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038360038111156111475761114761396b565b03610acb5773ffffffffffffffffffffffffffffffffffffffff8816600090815260048201602081905260409091205460ff161561118a57505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff881660009081526020829052604090205460ff16156111c357505050505050505050565b883f600090815260058301602081905260409091205460ff16156111ed5750505050505050505050565b883f60009081526020829052604090205460ff16156111015750505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120546112589061010090046effffffffffffffffffffffffffffff16836123e3565b9392505050565b8261126981612a9a565b8160008190036112a5576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb578686828181106112e2576112e2613b3d565b90506020020160208101906112f79190613740565b91506113038383612be5565b156113aa5773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660016040517f503012490a650739416858609e898957b874d17415a062945179c5735797884090600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b6001016112c8565b6107d6816119bb565b826113c581612a9a565b816000819003611401576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb5786868281811061143e5761143e613b3d565b60200291909101359250829050611481576040517f2bb30b6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148e6002840183612c07565b1561150b57816effffffffffffffffffffffffffffff891660016040517fc8615322788d404dfe307db9eef031bc148d1cec5e270a1fd6528a02b445d44590600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611424565b6effffffffffffffffffffffffffffff81166000908152600560205260409020606090610c1990600201612bd8565b600061125883836120b6565b8261155881612a9a565b816000819003611594576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb578686828181106115d1576115d1613b3d565b9050602002013591506115f08284600201612c1390919063ffffffff16565b1561166a57816effffffffffffffffffffffffffffff891660016040517f061d78094976b1d9ae7bb858f141c915b46152756409caadb07482983c2ca30190600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b6001016115b7565b600081156116b0576effffffffffffffffffffffffffffff83166000908152600560208181526040808420868552909201905290205460ff16611258565b50600092915050565b826116c381612a9a565b8160008190036116ff576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb5786868281811061173c5761173c613b3d565b90506020020160208101906117519190613740565b915061175d8383612be5565b156118045773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660006040517f503012490a650739416858609e898957b874d17415a062945179c5735797884090600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600101611722565b73ffffffffffffffffffffffffffffffffffffffff8116611859576040517f1f4ee59800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104f08282612c1f565b6effffffffffffffffffffffffffffff81166000908152600460205260409020606090610c1990600201612bd8565b6104f0828261180c565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526003602090815260408083205461010090046effffffffffffffffffffffffffffff168352600480835281842094861684529390930190529081205460ff16611258565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409081902081518083019092528054829060ff1660088111156119585761195861396b565b60088111156119695761196961396b565b8152905461010090046effffffffffffffffffffffffffffff1660209091015292915050565b6effffffffffffffffffffffffffffff81166000908152600560205260409020606090610c1990612bd8565b6107d6816000612c1f565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526003602090815260408083205461010090046effffffffffffffffffffffffffffff168352600582528083209385168352600490930190529081205460ff16611258565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff16611513565b6effffffffffffffffffffffffffffff8216600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260040190915281205460ff16611258565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff16610c1f565b3360009081526020819052604090205460ff1615611b4e576040517fce8c510800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7a7fd3f5cd7a1487f8f0a2a12cf6e95545173640e44a3a845c5f2c9d00175aab4294848484612cb6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bde576040517f7640718d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fe7f8d62df5af850daa5d677e9e5c8065b7b549ec99ae61ba0ffaa9f5bf3e2d039190a2505050565b60008080836008811115611c5757611c5761396b565b03611c685750600290506000915091565b6001836008811115611c7c57611c7c61396b565b03611c8c57506000905080915091565b6002836008811115611ca057611ca061396b565b03611cb15750600190506000915091565b6003836008811115611cc557611cc561396b565b03611cd65750600290506000915091565b6004836008811115611cea57611cea61396b565b03611cfb5750600390506000915091565b6005836008811115611d0f57611d0f61396b565b03611d205750600290506001915091565b6006836008811115611d3457611d3461396b565b03611d4457506002905080915091565b6007836008811115611d5857611d5861396b565b03611d695750600390506001915091565b50600390506002915091565b82611d7f81612a9a565b816000819003611dbb576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260056020526040812090805b85811015610acb57868682818110611df857611df8613b3d565b9050602002016020810190611e0d9190613740565b915073ffffffffffffffffffffffffffffffffffffffff8216611e5c576040517f64019f1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e668383612b1f565b15611f105773ffffffffffffffffffffffffffffffffffffffff82166effffffffffffffffffffffffffffff891660016040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff82166000908152600484016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611dde565b82611f2281612a9a565b816000819003611f5e576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb57868682818110611f9b57611f9b613b3d565b60200291909101359250829050611fde576040517f2bb30b6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611feb6002840183612c07565b1561206857816effffffffffffffffffffffffffffff891660006040517fc8615322788d404dfe307db9eef031bc148d1cec5e270a1fd6528a02b445d44590600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611f81565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120546112589061010090046effffffffffffffffffffffffffffff1683611672565b60018054600091829182906120db906effffffffffffffffffffffffffffff16613b9b565b91906101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff160217905590506121173390565b6effffffffffffffffffffffffffffff82166000818152600260205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff949094169390931790925590517f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be14906121ae9087908790613bc9565b60405180910390a260405133906effffffffffffffffffffffffffffff8316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736790600090a39392505050565b604080516060810182526000808252602082018190529181019190915273ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604080822081518083019092528054829060ff16600881111561225e5761225e61396b565b600881111561226f5761226f61396b565b8152905461010090046effffffffffffffffffffffffffffff166020909101526040805160608101909152815191925090819060088111156122b3576122b361396b565b815260200182602001516effffffffffffffffffffffffffffff16815260200182602001516effffffffffffffffffffffffffffff16815250915050919050565b6122fd82612cde565b6001546effffffffffffffffffffffffffffff908116908216111561234e576040517ff716872600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602052604080822080547fffffffffffffffffffffffffffffffff000000000000000000000000000000ff166101006effffffffffffffffffffffffffffff87169081029190911790915590519092917fa66ff5557b7dc1562bb5e83306e15b513a25aa7537369bce38fc29c20847a79191a35050565b600081156116b0576effffffffffffffffffffffffffffff8316600090815260046020908152604080832085845260050190915290205460ff16611258565b61242b82612cde565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600881111561248b5761248b61396b565b02179055508173ffffffffffffffffffffffffffffffffffffffff167fb39d8f1e6f05413a407e46fc950eb92e9f5b3d65a47c3f0bdc7a2741a6ec0f7d826040516124d69190613c16565b60405180910390a25050565b6001805460009182918290612507906effffffffffffffffffffffffffffff16613b9b565b91906101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff16021790559050600181036effffffffffffffffffffffffffffff16836effffffffffffffffffffffffffffff16111561259b576040517ff716872600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff81166000818152600260205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055517f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be14906126159088908890613bc9565b60405180910390a260405133906effffffffffffffffffffffffffffff8316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736790600090a36effffffffffffffffffffffffffffff8084166000908152600460208181526040808420600580845282862096881686529383528185209390925283209093926126a790868685612eb7565b6126b46000868685612fb8565b6126c16001868584612eb7565b6126ce6001868584612fb8565b5092979650505050505050565b826126e581612a9a565b816000819003612721576040517fd13675da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8516600090815260046020526040812090805b85811015610acb5786868281811061275e5761275e613b3d565b90506020020135915061277d8284600201612c1390919063ffffffff16565b156127f757816effffffffffffffffffffffffffffff891660006040517f061d78094976b1d9ae7bb858f141c915b46152756409caadb07482983c2ca30190600090a46000828152600584016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600101612744565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054606090610c199061010090046effffffffffffffffffffffffffffff1661198f565b3360009081526020819052604090205460ff1615612891576040517fce8c510800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128f17fd3f5cd7a1487f8f0a2a12cf6e95545173640e44a3a845c5f2c9d00175aab429483838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061308692505050565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612955576040517f7640718d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fe7f8d62df5af850daa5d677e9e5c8065b7b549ec99ae61ba0ffaa9f5bf3e2d039190a25050565b816129c181612a9a565b6effffffffffffffffffffffffffffff831660009081526005602052604090206129eb8184612b1f565b15610d265773ffffffffffffffffffffffffffffffffffffffff83166effffffffffffffffffffffffffffff851660016040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff83166000908152600482016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550505050565b6effffffffffffffffffffffffffffff811660009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107d6576040517f4e680cb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006112588373ffffffffffffffffffffffffffffffffffffffff84166130aa565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f89a9c855000000000000000000000000000000000000000000000000000000001480610c1957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610c19565b60606000611258836130f9565b60006112588373ffffffffffffffffffffffffffffffffffffffff8416613155565b600061125883836130aa565b60006112588383613155565b612c2882612a9a565b6effffffffffffffffffffffffffffff821660008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590519092917f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736791a35050565b6000806000612cc787878787613248565b91509150612cd481613337565b5095945050505050565b6000813b15612e8057503373ffffffffffffffffffffffffffffffffffffffff82161480612e80578173ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612d8b575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612d8891810190613c24565b60015b15612dab5773ffffffffffffffffffffffffffffffffffffffff16331490505b80612e805773ffffffffffffffffffffffffffffffffffffffff82166391d148546000336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925273ffffffffffffffffffffffffffffffffffffffff166024820152604401602060405180830381865afa925050508015612e78575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612e7591810190613c41565b60015b15612e805790505b806104f0576040517f7f954ba100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181600481016000612ec8846134ef565b90506000805b82811015612fac57612ee086826134f9565b9150612eec8583612b1f565b15612fa4578173ffffffffffffffffffffffffffffffffffffffff16896effffffffffffffffffffffffffffff168b6001811115612f2c57612f2c61396b565b6040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d1790600090a473ffffffffffffffffffffffffffffffffffffffff8216600090815260208590526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101612ece565b50505050505050505050565b6002808301908201600583016000612fcf846134ef565b90506000805b82811015612fac57612fe786826134f9565b9150612ff38583612c07565b1561307e5781896effffffffffffffffffffffffffffff168b600181111561301d5761301d61396b565b6040517fc8615322788d404dfe307db9eef031bc148d1cec5e270a1fd6528a02b445d44590600090a4600082815260208590526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101612fd5565b60008060006130958585613505565b915091506130a281613337565b509392505050565b60008181526001830160205260408120546130f157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610c19565b506000610c19565b60608160000180548060200260200160405190810160405280929190818152602001828054801561314957602002820191906000526020600020905b815481526020019060010190808311613135575b50505050509050919050565b6000818152600183016020526040812054801561323e576000613179600183613c63565b855490915060009061318d90600190613c63565b90508181146131f25760008660000182815481106131ad576131ad613b3d565b90600052602060002001549050808760000184815481106131d0576131d0613b3d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061320357613203613c76565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610c19565b6000915050610c19565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561327f575060009050600361332e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156132d3573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166133275760006001925092505061332e565b9150600090505b94509492505050565b600081600481111561334b5761334b61396b565b036133535750565b60018160048111156133675761336761396b565b036133d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b60028160048111156133e7576133e761396b565b0361344e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016133ca565b60038160048111156134625761346261396b565b036107d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016133ca565b6000610c19825490565b6000611258838361354a565b600080825160410361353b5760208301516040840151606085015160001a61352f87828585613248565b94509450505050613543565b506000905060025b9250929050565b600082600001828154811061356157613561613b3d565b9060005260206000200154905092915050565b80356effffffffffffffffffffffffffffff8116811461359357600080fd5b919050565b60008083601f8401126135aa57600080fd5b50813567ffffffffffffffff8111156135c257600080fd5b6020830191508360208260051b850101111561354357600080fd5b6000806000604084860312156135f257600080fd5b6135fb84613574565b9250602084013567ffffffffffffffff81111561361757600080fd5b61362386828701613598565b9497909650939450505050565b60006020828403121561364257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461125857600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146107d657600080fd5b600080604083850312156136a757600080fd5b6136b083613574565b915060208301356136c081613672565b809150509250929050565b6000602082840312156136dd57600080fd5b61125882613574565b6020808252825182820181905260009190848201906040850190845b8181101561373457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613702565b50909695505050505050565b60006020828403121561375257600080fd5b813561125881613672565b6020808252825182820181905260009190848201906040850190845b8181101561373457835183529284019291840191600101613779565b600080604083850312156137a857600080fd5b82356137b381613672565b91506137c160208401613574565b90509250929050565b6000806000606084860312156137df57600080fd5b83356137ea81613672565b925060208401356137fa81613672565b9150604084013561380a81613672565b809150509250925092565b6000806040838503121561382857600080fd5b823561383381613672565b946020939093013593505050565b600060208083528351808285015260005b8181101561386e57858101830151858201604001528201613852565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008083601f8401126138bf57600080fd5b50813567ffffffffffffffff8111156138d757600080fd5b60208301915083602082850101111561354357600080fd5b6000806020838503121561390257600080fd5b823567ffffffffffffffff81111561391957600080fd5b613925858286016138ad565b90969095509350505050565b6000806040838503121561394457600080fd5b61383383613574565b6000806040838503121561396057600080fd5b82356136b081613672565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600981106139aa576139aa61396b565b9052565b60006040820190506139c182845161399a565b6020928301516effffffffffffffffffffffffffffff16919092015290565b6000806000606084860312156139f557600080fd5b833560ff81168114613a0657600080fd5b95602085013595506040909401359392505050565b80356009811061359357600080fd5b600060208284031215613a3c57600080fd5b61125882613a1b565b6040810160048410613a5957613a5961396b565b83825260038310613a6c57613a6c61396b565b8260208301529392505050565b6000606082019050613a8c82845161399a565b60208301516effffffffffffffffffffffffffffff8082166020850152806040860151166040850152505092915050565b60008060408385031215613ad057600080fd5b8235613adb81613672565b91506137c160208401613a1b565b600080600060408486031215613afe57600080fd5b833567ffffffffffffffff811115613b1557600080fd5b613b21868287016138ad565b9094509250613b34905060208501613574565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006effffffffffffffffffffffffffffff808316818103613bbf57613bbf613b6c565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60208101610c19828461399a565b600060208284031215613c3657600080fd5b815161125881613672565b600060208284031215613c5357600080fd5b8151801515811461125857600080fd5b81810381811115610c1957610c19613b6c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220b2e22ffac36fef1d4cc736309089b3d0e9c332fda01fd4faf1593371ad9d647a64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000067985b1f8b613b57077bbdb24a5defcdda458317
-----Decoded View---------------
Arg [0] : defaultOwner (address): 0x67985B1f8B613b57077bbDb24A5DEFCDDA458317
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000067985b1f8b613b57077bbdb24a5defcdda458317
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ 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.