Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 3 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
19565344 | 91 days ago | Contract Creation | 0 ETH | |||
19565344 | 91 days ago | Contract Creation | 0 ETH | |||
19565344 | 91 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
StrictAuthorizedTransferSecurityRegistry
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import { ListTypes, TransferSecurityLevels, IStrictAuthorizedTransferSecurityRegistry } from "./interfaces/IStrictAuthorizedTransferSecurityRegistry.sol"; import { ICreatorTokenTransferValidator } from "./interfaces/ICreatorTokenTransferValidator.sol"; import { IOwnable } from "./interfaces/IOwnable.sol"; import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import { Tstorish } from "tstorish/Tstorish.sol"; import { IEOARegistry } from "./interfaces/IEOARegistry.sol"; import { StrictAuthorizedTransferSecurityRegistryExtraViewFns } from "./StrictAuthorizedTransferSecurityRegistryExtraViewFns.sol"; /// @title StrictAuthorizedTransferSecurityRegistry /// @dev Implementation of a simplified version of the Transfer Security Registry that only /// supports authorizers and whitelisted operators, and allows collections to disable /// direct transfers (where caller == from) and contract recipients (requiring EOA /// registration by providing a signature). Note that a number of view functions on /// collections that add this validator will not work. contract StrictAuthorizedTransferSecurityRegistry is Tstorish, IStrictAuthorizedTransferSecurityRegistry, ERC165 { using EnumerableSet for EnumerableSet.AddressSet; /** * @dev This struct is used internally to represent an enumerable list of accounts. */ struct AccountList { EnumerableSet.AddressSet enumerableAccounts; mapping (address => bool) nonEnumerableAccounts; } /** * @dev This struct is used internally for the storage of authorizer + operator lists. */ struct List { address owner; AccountList authorizers; AccountList operators; AccountList blacklist; } struct CollectionConfiguration { uint120 listId; bool policyBypassed; bool blacklistBased; bool directTransfersDisabled; bool contractRecipientsDisabled; bool signatureRegistrationRequired; } /// @dev The default admin role value for contracts that implement access control. bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00; /// @notice Keeps track of the most recently created list id. uint120 public lastListId; /// @dev Mapping of list ids to list settings mapping (uint120 => List) private lists; /// @dev Mapping of collection addresses to list ids & security policies. mapping (address => CollectionConfiguration) private collectionConfiguration; // TSTORE slot: scope ++ 8 empty bytes ++ collection bytes4 private constant _AUTHORIZED_OPERATOR_SCOPE = 0x596a397a; // TSTORE slot: keccak256(scope ++ identifier ++ collection) bytes4 private constant _AUTHORIZED_IDENTIFIER_SCOPE = 0x7e746c61; // TSTORE slot: keccak256(scope ++ identifier ++ collection) bytes4 private constant _AUTHORIZED_AMOUNT_SCOPE = 0x71836d45; address private immutable _EXTRA_VIEW_FUNCTIONS; IEOARegistry private immutable _EOA_REGISTRY; /** * @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 StrictAuthorizedTransferSecurityRegistry__ArrayLengthCannotBeZero(); } _; } constructor(address defaultOwner, address eoaRegistry) { uint120 id = 0; lists[id].owner = defaultOwner; emit CreatedList(id, "DEFAULT LIST"); emit ReassignedListOwnership(id, defaultOwner); // Deploy a contract containing legacy view functions. _EXTRA_VIEW_FUNCTIONS = address(new StrictAuthorizedTransferSecurityRegistryExtraViewFns()); _EOA_REGISTRY = IEOARegistry(eoaRegistry); } // Delegatecall to contract with legacy view functions in the fallback. fallback() external { address target = _EXTRA_VIEW_FUNCTIONS; assembly { calldatacopy(0, 0, calldatasize()) let status := delegatecall(gas(), target, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch status case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /// Manage lists of authorizers & operators that can be applied to collections function createList(string calldata name) external returns (uint120) { uint120 id = ++lastListId; lists[id].owner = msg.sender; emit CreatedList(id, name); emit ReassignedListOwnership(id, msg.sender); return id; } function createListCopy(string calldata name, uint120 sourceListId) external override returns (uint120) { uint120 id = ++lastListId; unchecked { if (sourceListId > id - 1) { revert StrictAuthorizedTransferSecurityRegistry__ListDoesNotExist(); } } List storage sourceList = lists[sourceListId]; List storage targetList = lists[id]; targetList.owner = msg.sender; emit CreatedList(id, name); emit ReassignedListOwnership(id, msg.sender); _copyAddressSet(ListTypes.AuthorizerList, id, sourceList.authorizers, targetList.authorizers); _copyAddressSet(ListTypes.OperatorList, id, sourceList.operators, targetList.operators); _copyAddressSet(ListTypes.OperatorRequiringAuthorizationList, id, sourceList.blacklist, targetList.blacklist); return id; } function reassignOwnershipOfList(uint120 id, address newOwner) external onlyListOwner(id) { if (newOwner == address(0)) { revert StrictAuthorizedTransferSecurityRegistry__ListOwnershipCannotBeTransferredToZeroAddress(); } lists[id].owner = newOwner; emit ReassignedListOwnership(id, newOwner); } function renounceOwnershipOfList(uint120 id) external onlyListOwner(id) { lists[id].owner = address(0); emit ReassignedListOwnership(id, address(0)); } function applyListToCollection(address collection, uint120 id) external { _requireCallerIsNFTOrContractOwnerOrAdmin(collection); if (id > lastListId) { revert StrictAuthorizedTransferSecurityRegistry__ListDoesNotExist(); } collectionConfiguration[collection].listId = id; emit AppliedListToCollection(collection, id); } function listOwners(uint120 id) external view returns (address) { return lists[id].owner; } /// Manage and query for authorizers on lists function addAccountToAuthorizers(uint120 id, address account) external onlyListOwner(id) { address[] memory accounts = new address[](1); accounts[0] = account; _addAccounts(id, accounts, lists[id].authorizers, ListTypes.AuthorizerList); } function addAccountsToAuthorizers(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _addAccounts(id, accounts, lists[id].authorizers, ListTypes.AuthorizerList); } function addAuthorizers(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _addAccounts(id, accounts, lists[id].authorizers, ListTypes.AuthorizerList); } function removeAccountFromAuthorizers(uint120 id, address account) external onlyListOwner(id) { address[] memory accounts = new address[](1); accounts[0] = account; _removeAccounts(id, accounts, lists[id].authorizers, ListTypes.AuthorizerList); } function removeAccountsFromAuthorizers(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _removeAccounts(id, accounts, lists[id].authorizers, ListTypes.AuthorizerList); } function getAuthorizerAccounts(uint120 id) external view returns (address[] memory) { return lists[id].authorizers.enumerableAccounts.values(); } function isAccountAuthorizer(uint120 id, address account) external view returns (bool) { return lists[id].authorizers.nonEnumerableAccounts[account]; } function getAuthorizerAccountsByCollection(address collection) external view returns (address[] memory) { return lists[collectionConfiguration[collection].listId].authorizers.enumerableAccounts.values(); } function isAccountAuthorizerOfCollection(address collection, address account) external view returns (bool) { return lists[collectionConfiguration[collection].listId].authorizers.nonEnumerableAccounts[account]; } function _ensureCallerIsCollectionAuthorizer(address collection) internal view { if (!lists[collectionConfiguration[collection].listId].authorizers.nonEnumerableAccounts[msg.sender]) { revert StrictAuthorizedTransferSecurityRegistry__CallerIsNotValidAuthorizer(); } } /// Manage and query for operators on lists function addAccountToWhitelist(uint120 id, address account) external onlyListOwner(id) { address[] memory accounts = new address[](1); accounts[0] = account; _addAccounts(id, accounts, lists[id].operators, ListTypes.OperatorList); } function addAccountsToWhitelist(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _addAccounts(id, accounts, lists[id].operators, ListTypes.OperatorList); } function addOperators(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _addAccounts(id, accounts, lists[id].operators, ListTypes.OperatorList); } function removeAccountFromWhitelist(uint120 id, address account) external onlyListOwner(id) { address[] memory accounts = new address[](1); accounts[0] = account; _removeAccounts(id, accounts, lists[id].operators, ListTypes.OperatorList); } function removeAccountsFromWhitelist(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _removeAccounts(id, accounts, lists[id].operators, ListTypes.OperatorList); } function getWhitelistedAccounts(uint120 id) external view returns (address[] memory) { return lists[id].operators.enumerableAccounts.values(); } function isAccountWhitelisted(uint120 id, address account) external view returns (bool) { return lists[id].operators.nonEnumerableAccounts[account]; } function getWhitelistedAccountsByCollection(address collection) external view returns (address[] memory) { return lists[collectionConfiguration[collection].listId].operators.enumerableAccounts.values(); } function isAccountWhitelistedByCollection(address collection, address account) external view returns (bool) { return lists[collectionConfiguration[collection].listId].operators.nonEnumerableAccounts[account]; } /// Manage and query for blacklists on lists function addAccountToBlacklist(uint120 id, address account) external onlyListOwner(id) { address[] memory accounts = new address[](1); accounts[0] = account; _addAccounts(id, accounts, lists[id].blacklist, ListTypes.OperatorRequiringAuthorizationList); } function addAccountsToBlacklist(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _addAccounts(id, accounts, lists[id].blacklist, ListTypes.OperatorRequiringAuthorizationList); } function removeAccountFromBlacklist(uint120 id, address account) external onlyListOwner(id) { address[] memory accounts = new address[](1); accounts[0] = account; _removeAccounts(id, accounts, lists[id].blacklist, ListTypes.OperatorRequiringAuthorizationList); } function removeAccountsFromBlacklist(uint120 id, address[] calldata accounts) external onlyListOwner(id) notZero(accounts.length) { _removeAccounts(id, accounts, lists[id].blacklist, ListTypes.OperatorRequiringAuthorizationList); } function getBlacklistedAccounts(uint120 id) external view returns (address[] memory) { return lists[id].blacklist.enumerableAccounts.values(); } function isAccountBlacklisted(uint120 id, address account) external view returns (bool) { return lists[id].blacklist.nonEnumerableAccounts[account]; } function getBlacklistedAccountsByCollection(address collection) external view returns (address[] memory) { return lists[collectionConfiguration[collection].listId].blacklist.enumerableAccounts.values(); } function isAccountBlacklistedByCollection(address collection, address account) external view returns (bool) { return lists[collectionConfiguration[collection].listId].blacklist.nonEnumerableAccounts[account]; } /// Ensure that a specific operator has been authorized to transfer tokens function validateTransfer(address caller, address from, address to) external view { _validateTransfer(caller, from, to); } /// Ensure that a transfer has been authorized for a specific tokenId function validateTransfer(address caller, address from, address to, uint256 tokenId) external view { _validateTransferByIdentifer(caller, from, to, tokenId); } /// Ensure that a transfer has been authorized for a specific amount of a specific tokenId, and /// reduce the transferable amount remaining function validateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount) external { _validateTransferByAmount(caller, from, to, tokenId, amount); } /// Legacy alias for validateTransfer (address caller, address from, address to) function applyCollectionTransferPolicy(address caller, address from, address to) external view { _validateTransfer(caller, from, to); } /// Temporarily assign a specific allowed operator for a given collection function beforeAuthorizedTransfer(address operator, address token) external { _ensureCallerIsCollectionAuthorizer(token); _setTstorish( _getAuthorizedOperatorSlot(token), uint256(uint160(operator)) ); } /// Clear assignment of a specific allowed operator for a given collection function afterAuthorizedTransfer(address token) external { _ensureCallerIsCollectionAuthorizer(token); _clearTstorish(_getAuthorizedOperatorSlot(token)); } /// Temporarily allow a specific tokenId from a given collection to be transferred function beforeAuthorizedTransfer(address token, uint256 tokenId) external { _ensureCallerIsCollectionAuthorizer(token); _setTstorish( _getAuthorizedIdentifierSlot(token, tokenId), 1 ); } /// Clear assignment of an specific tokenId's transfer allowance function afterAuthorizedTransfer(address token, uint256 tokenId) external { _ensureCallerIsCollectionAuthorizer(token); _clearTstorish(_getAuthorizedIdentifierSlot(token, tokenId)); } /// Temporarily allow a specific amount of a specific tokenId from a given collection to be transferred function beforeAuthorizedTransferWithAmount(address token, uint256 tokenId, uint256 amount) external { _ensureCallerIsCollectionAuthorizer(token); uint256 slot = _getAuthorizedAmountSlot(token, tokenId); uint256 currentAmount = _getTstorish(slot); uint256 newAmount = currentAmount + amount; _setTstorish(slot, newAmount); } /// Clear assignment of a tokenId's transfer allowance for a specific amount function afterAuthorizedTransferWithAmount(address token, uint256 tokenId) external { _ensureCallerIsCollectionAuthorizer(token); _clearTstorish(_getAuthorizedAmountSlot(token, tokenId)); } function setTransferSecurityLevelOfCollection( address collection, uint8 level, bool enableAuthorizationMode, bool authorizersCanSetWildcardOperators, bool enableAccountFreezingMode ) external { if (!enableAuthorizationMode || !authorizersCanSetWildcardOperators || enableAccountFreezingMode) { revert StrictAuthorizedTransferSecurityRegistry__UnsupportedSecurityLevelDetail(); } _setTransferSecurityLevelOfCollection(collection, TransferSecurityLevels(level)); } function setTransferSecurityLevelOfCollection( address collection, TransferSecurityLevels level ) external { _setTransferSecurityLevelOfCollection(collection, level); } function isVerifiedEOA(address account) external view returns (bool) { return _EOA_REGISTRY.isVerifiedEOA(account); } /// @notice ERC-165 Interface Support function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165) returns (bool) { return interfaceId == type(ICreatorTokenTransferValidator).interfaceId || interfaceId == type(IStrictAuthorizedTransferSecurityRegistry).interfaceId || super.supportsInterface(interfaceId); } function _setTransferSecurityLevelOfCollection( address collection, TransferSecurityLevels level ) internal { _requireCallerIsNFTOrContractOwnerOrAdmin(collection); if (level == TransferSecurityLevels.Recommended) { level = TransferSecurityLevels.Three; } CollectionConfiguration storage config = collectionConfiguration[collection]; if (level == TransferSecurityLevels.One) { config.policyBypassed = true; config.blacklistBased = false; config.directTransfersDisabled = false; config.contractRecipientsDisabled = false; config.signatureRegistrationRequired = false; } else if (level == TransferSecurityLevels.Two) { config.policyBypassed = false; config.blacklistBased = true; config.directTransfersDisabled = false; config.contractRecipientsDisabled = false; config.signatureRegistrationRequired = false; } else if (level == TransferSecurityLevels.Three) { config.policyBypassed = false; config.blacklistBased = false; config.directTransfersDisabled = false; config.contractRecipientsDisabled = false; config.signatureRegistrationRequired = false; } else if (level == TransferSecurityLevels.Four) { config.policyBypassed = false; config.blacklistBased = false; config.directTransfersDisabled = true; config.contractRecipientsDisabled = false; config.signatureRegistrationRequired = false; } else if (level == TransferSecurityLevels.Five) { config.policyBypassed = false; config.blacklistBased = false; config.directTransfersDisabled = false; config.contractRecipientsDisabled = true; config.signatureRegistrationRequired = false; } else if (level == TransferSecurityLevels.Six) { config.policyBypassed = false; config.blacklistBased = false; config.directTransfersDisabled = false; config.contractRecipientsDisabled = false; config.signatureRegistrationRequired = true; } else if (level == TransferSecurityLevels.Seven) { config.policyBypassed = false; config.blacklistBased = false; config.directTransfersDisabled = true; config.contractRecipientsDisabled = true; config.signatureRegistrationRequired = false; } else if (level == TransferSecurityLevels.Eight) { config.policyBypassed = false; config.blacklistBased = false; config.directTransfersDisabled = true; config.contractRecipientsDisabled = false; config.signatureRegistrationRequired = true; } else { revert StrictAuthorizedTransferSecurityRegistry__UnsupportedSecurityLevel(); } emit SetTransferSecurityLevel(collection, level); } /** * @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, AccountList storage ptrFromList, AccountList 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 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 (msg.sender != lists[id].owner) { revert StrictAuthorizedTransferSecurityRegistry__CallerDoesNotOwnList(); } } /** * @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 { if (msg.sender == tokenAddress) { return; } if (msg.sender == _safeOwner(tokenAddress)) { return; } if (!_safeHasRole(tokenAddress)) { revert StrictAuthorizedTransferSecurityRegistry__CallerMustHaveElevatedPermissionsForSpecifiedNFT(); } } /** * @dev A gas efficient, and fallback-safe way to call the owner function on a token contract. * This will get the owner if it exists - and when the function is unimplemented, the * presence of a fallback function will not result in halted execution. */ function _safeOwner( address tokenAddress ) internal view returns(address owner) { assembly { mstore(0x00, 0x8da5cb5b) let status := staticcall(gas(), tokenAddress, 0x1c, 0x04, 0x00, 0x20) if and(iszero(lt(returndatasize(), 0x20)), status) { owner := mload(0x00) } } } /** * @dev A gas efficient, and fallback-safe way to call the hasRole function on a token contract. * This will check if the account `hasRole` if `hasRole` exists - and when the function is unimplemented, the * presence of a fallback function will not result in halted execution. */ function _safeHasRole( address tokenAddress ) internal view returns(bool hasRole) { assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x60)) mstore(ptr, 0x91d14854) mstore(add(0x20, ptr), DEFAULT_ACCESS_CONTROL_ADMIN_ROLE) mstore(add(0x40, ptr), caller()) let status := staticcall(gas(), tokenAddress, add(ptr, 0x1c), 0x44, 0x00, 0x20) if and(iszero(lt(returndatasize(), 0x20)), status) { hasRole := mload(0x00) } } } /** * @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) } } function _addAccounts( uint120 id, address[] memory accounts, AccountList storage accountList, ListTypes listType ) internal { address account; for (uint256 i = 0; i < accounts.length;) { account = accounts[i]; if (account == address(0)) { revert StrictAuthorizedTransferSecurityRegistry__ZeroAddressNotAllowed(); } if (accountList.enumerableAccounts.add(account)) { emit AddedAccountToList(listType, id, account); accountList.nonEnumerableAccounts[account] = true; } unchecked { ++i; } } } function _removeAccounts( uint120 id, address[] memory accounts, AccountList storage accountList, ListTypes listType ) internal { address account; for (uint256 i = 0; i < accounts.length;) { account = accounts[i]; if (accountList.enumerableAccounts.remove(account)) { emit RemovedAccountFromList(listType, id, account); delete accountList.nonEnumerableAccounts[account]; } unchecked { ++i; } } } function _validateTransfer(address operator, address from, address to) internal view { CollectionConfiguration memory config = collectionConfiguration[msg.sender]; if (config.policyBypassed) { return; } if (config.contractRecipientsDisabled) { if (to.code.length != 0) { revert StrictAuthorizedTransferSecurityRegistry__ReceiverMustNotHaveDeployedCode(); } } if (config.signatureRegistrationRequired) { if (!_EOA_REGISTRY.isVerifiedEOA(to)) { revert StrictAuthorizedTransferSecurityRegistry__ReceiverProofOfEOASignatureUnverified(); } } if (operator == from) { if (config.directTransfersDisabled) { revert StrictAuthorizedTransferSecurityRegistry__CallerMustBeWhitelistedOperator(); } return; } uint256 slot = _getAuthorizedOperatorSlot(msg.sender); if (operator == address(uint160(_getTstorish(slot)))) { return; } if (config.blacklistBased) { if (lists[config.listId].blacklist.nonEnumerableAccounts[operator]) { revert StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); } } else { if (!lists[config.listId].operators.nonEnumerableAccounts[operator]) { revert StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); } } } function _validateTransferByIdentifer(address operator, address from, address to, uint256 identifier) internal view { CollectionConfiguration memory config = collectionConfiguration[msg.sender]; if (config.policyBypassed) { return; } if (config.contractRecipientsDisabled) { if (to.code.length != 0) { revert StrictAuthorizedTransferSecurityRegistry__ReceiverMustNotHaveDeployedCode(); } } if (config.signatureRegistrationRequired) { if (!_EOA_REGISTRY.isVerifiedEOA(to)) { revert StrictAuthorizedTransferSecurityRegistry__ReceiverProofOfEOASignatureUnverified(); } } if (operator == from) { if (config.directTransfersDisabled) { revert StrictAuthorizedTransferSecurityRegistry__CallerMustBeWhitelistedOperator(); } return; } uint256 slot = _getAuthorizedIdentifierSlot(msg.sender, identifier); uint256 authorizedIdentifier = _getTstorish(slot); if (authorizedIdentifier != 0) { return; } if (config.blacklistBased) { if (lists[config.listId].blacklist.nonEnumerableAccounts[operator]) { revert StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); } } else { if (!lists[config.listId].operators.nonEnumerableAccounts[operator]) { revert StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); } } } function _validateTransferByAmount(address operator, address from, address to, uint256 identifier, uint256 amount) internal { CollectionConfiguration memory config = collectionConfiguration[msg.sender]; if (config.policyBypassed) { return; } if (config.contractRecipientsDisabled) { if (to.code.length != 0) { revert StrictAuthorizedTransferSecurityRegistry__ReceiverMustNotHaveDeployedCode(); } } if (config.signatureRegistrationRequired) { if (!_EOA_REGISTRY.isVerifiedEOA(to)) { revert StrictAuthorizedTransferSecurityRegistry__ReceiverProofOfEOASignatureUnverified(); } } if (operator == from) { if (config.directTransfersDisabled) { revert StrictAuthorizedTransferSecurityRegistry__CallerMustBeWhitelistedOperator(); } return; } uint256 slot = _getAuthorizedAmountSlot(msg.sender, identifier); uint256 authorizedAmount = _getTstorish(slot); if (authorizedAmount >= amount) { unchecked { _setTstorish(slot, authorizedAmount - amount); } return; } if (config.blacklistBased) { if (lists[config.listId].blacklist.nonEnumerableAccounts[operator]) { revert StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); } } else { if (!lists[config.listId].operators.nonEnumerableAccounts[operator]) { revert StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); } } } function _getAuthorizedOperatorSlot( address collection ) internal pure returns (uint256 slot) { bytes4 authorizedOperatorScope = _AUTHORIZED_OPERATOR_SCOPE; assembly { slot := or( authorizedOperatorScope, and(collection, 0xffffffffffffffffffffffffffffffffffffffff) ) } } function _getAuthorizedIdentifierSlot( address collection, uint256 identifier ) internal pure returns (uint256 slot) { bytes4 authorizedIdentifierScope = _AUTHORIZED_IDENTIFIER_SCOPE; assembly { mstore(0x0, authorizedIdentifierScope) mstore(0x18, collection) mstore(0x04, identifier) slot := keccak256(0x0, 0x38) } } function _getAuthorizedAmountSlot( address collection, uint256 identifier ) internal pure returns (uint256 slot) { bytes4 authorizedAmountScope = _AUTHORIZED_AMOUNT_SCOPE; assembly { mstore(0x0, authorizedAmountScope) mstore(0x18, collection) mstore(0x04, identifier) slot := keccak256(0x0, 0x38) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; enum ListTypes { AuthorizerList, OperatorList, OperatorRequiringAuthorizationList } enum TransferSecurityLevels { Recommended, One, Two, Three, Four, Five, Six, Seven, Eight } /// @title IStrictAuthorizedTransferSecurityRegistry /// @dev Interface for the Authorized Transfer Security Registry, a simplified version of the Transfer /// Security Registry that only supports authorizers and whitelisted operators, and assumes a /// security level of OperatorWhitelistEnableOTC + authorizers for all collections that use it. /// Note that a number of view functions on collections that add this validator will not work. interface IStrictAuthorizedTransferSecurityRegistry { 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 RemovedAccountFromList(ListTypes indexed kind, uint256 indexed id, address indexed account); event SetTransferSecurityLevel(address collection, TransferSecurityLevels level); error StrictAuthorizedTransferSecurityRegistry__ListDoesNotExist(); error StrictAuthorizedTransferSecurityRegistry__CallerDoesNotOwnList(); error StrictAuthorizedTransferSecurityRegistry__ArrayLengthCannotBeZero(); error StrictAuthorizedTransferSecurityRegistry__CallerMustHaveElevatedPermissionsForSpecifiedNFT(); error StrictAuthorizedTransferSecurityRegistry__ListOwnershipCannotBeTransferredToZeroAddress(); error StrictAuthorizedTransferSecurityRegistry__ZeroAddressNotAllowed(); error StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer(); error StrictAuthorizedTransferSecurityRegistry__CallerIsNotValidAuthorizer(); error StrictAuthorizedTransferSecurityRegistry__UnsupportedSecurityLevel(); error StrictAuthorizedTransferSecurityRegistry__UnsupportedSecurityLevelDetail(); error StrictAuthorizedTransferSecurityRegistry__CallerMustBeWhitelistedOperator(); error StrictAuthorizedTransferSecurityRegistry__ReceiverMustNotHaveDeployedCode(); error StrictAuthorizedTransferSecurityRegistry__ReceiverProofOfEOASignatureUnverified(); /// Manage lists of authorizers & operators that can be applied to collections 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 listOwners(uint120 id) external view returns (address); /// Manage and query for authorizers on lists function addAccountToAuthorizers(uint120 id, address account) external; function addAccountsToAuthorizers(uint120 id, address[] calldata accounts) external; function addAuthorizers(uint120 id, address[] calldata accounts) external; function removeAccountFromAuthorizers(uint120 id, address account) external; function removeAccountsFromAuthorizers(uint120 id, address[] calldata accounts) external; function getAuthorizerAccounts(uint120 id) external view returns (address[] memory); function isAccountAuthorizer(uint120 id, address account) external view returns (bool); function getAuthorizerAccountsByCollection(address collection) external view returns (address[] memory); function isAccountAuthorizerOfCollection(address collection, address account) external view returns (bool); /// Manage and query for operators on lists function addAccountToWhitelist(uint120 id, address account) external; function addAccountsToWhitelist(uint120 id, address[] calldata accounts) external; function addOperators(uint120 id, address[] calldata accounts) external; function removeAccountFromWhitelist(uint120 id, address account) external; function removeAccountsFromWhitelist(uint120 id, address[] calldata accounts) external; function getWhitelistedAccounts(uint120 id) external view returns (address[] memory); function isAccountWhitelisted(uint120 id, address account) external view returns (bool); function getWhitelistedAccountsByCollection(address collection) external view returns (address[] memory); function isAccountWhitelistedByCollection(address collection, address account) external view returns (bool); /// Manage and query for blacklists on lists function addAccountToBlacklist(uint120 id, address account) external; function addAccountsToBlacklist(uint120 id, address[] calldata accounts) external; function removeAccountFromBlacklist(uint120 id, address account) external; function removeAccountsFromBlacklist(uint120 id, address[] calldata accounts) external; function getBlacklistedAccounts(uint120 id) external view returns (address[] memory); function isAccountBlacklisted(uint120 id, address account) external view returns (bool); function getBlacklistedAccountsByCollection(address collection) external view returns (address[] memory); function isAccountBlacklistedByCollection(address collection, address account) external view returns (bool); function setTransferSecurityLevelOfCollection( address collection, uint8 level, bool enableAuthorizationMode, bool authorizersCanSetWildcardOperators, bool enableAccountFreezingMode ) external; function setTransferSecurityLevelOfCollection( address collection, TransferSecurityLevels level ) external; function isVerifiedEOA(address account) external view returns (bool); /// Ensure that a specific operator has been authorized to transfer tokens function validateTransfer(address caller, address from, address to) external view; /// Ensure that a transfer has been authorized for a specific tokenId function validateTransfer(address caller, address from, address to, uint256 tokenId) external view; /// Ensure that a transfer has been authorized for a specific amount of a specific tokenId, and /// reduce the transferable amount remaining function validateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount) external; /// Legacy alias for validateTransfer (address caller, address from, address to) function applyCollectionTransferPolicy(address caller, address from, address to) external view; /// Temporarily assign a specific allowed operator for a given collection function beforeAuthorizedTransfer(address operator, address token) external; /// Clear assignment of a specific allowed operator for a given collection function afterAuthorizedTransfer(address token) external; /// Temporarily allow a specific tokenId from a given collection to be transferred function beforeAuthorizedTransfer(address token, uint256 tokenId) external; /// Clear assignment of an specific tokenId's transfer allowance function afterAuthorizedTransfer(address token, uint256 tokenId) external; /// Temporarily allow a specific amount of a specific tokenId from a given collection to be transferred function beforeAuthorizedTransferWithAmount(address token, uint256 tokenId, uint256 amount) external; /// Clear assignment of a tokenId's transfer allowance for a specific amount function afterAuthorizedTransferWithAmount(address token, uint256 tokenId) external; }
// 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; interface IOwnable { function owner() external view returns (address); }
// 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 // 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 pragma solidity ^0.8.24; contract Tstorish { // Declare a storage variable indicating if TSTORE support has been // activated post-deployment. bool private _tstoreSupport; /* * ------------------------------------------------------------------------+ * Opcode | Mnemonic | Stack | Memory | * ------------------------------------------------------------------------| * 60 0x02 | PUSH1 0x02 | 0x02 | | * 60 0x1e | PUSH1 0x1e | 0x1e 0x02 | | * 61 0x3d5c | PUSH2 0x3d5c | 0x3d5c 0x1e 0x02 | | * 3d | RETURNDATASIZE | 0 0x3d5c 0x1e 0x02 | | * | * :: store deployed bytecode in memory: (3d) RETURNDATASIZE (5c) TLOAD :: | * 52 | MSTORE | 0x1e 0x02 | [0..0x20): 0x3d5c | * f3 | RETURN | | [0..0x20): 0x3d5c | * ------------------------------------------------------------------------+ */ uint256 constant _TLOAD_TEST_PAYLOAD = 0x6002_601e_613d5c_3d_52_f3; uint256 constant _TLOAD_TEST_PAYLOAD_LENGTH = 0x0a; uint256 constant _TLOAD_TEST_PAYLOAD_OFFSET = 0x16; // Declare an immutable variable to store the tstore test contract address. address private immutable _tloadTestContract; // Declare an immutable variable to store the initial TSTORE support status. bool private immutable _tstoreInitialSupport; // Declare an immutable function type variable for the _setTstorish function // based on chain support for tstore at time of deployment. function(uint256,uint256) internal immutable _setTstorish; // Declare an immutable function type variable for the _getTstorish function // based on chain support for tstore at time of deployment. function(uint256) view returns (uint256) internal immutable _getTstorish; // Declare an immutable function type variable for the _clearTstorish function // based on chain support for tstore at time of deployment. function(uint256) internal immutable _clearTstorish; // Declare a few custom revert error types. error TStoreAlreadyActivated(); error TStoreNotSupported(); error TloadTestContractDeploymentFailed(); error OnlyDirectCalls(); /** * @dev Determine TSTORE availability during deployment. This involves * attempting to deploy a contract that utilizes TLOAD as part of the * contract construction bytecode, and configuring initial support for * using TSTORE in place of SSTORE based on the result. */ constructor() { // Deploy the contract testing TLOAD support and store the address. address tloadTestContract = _prepareTloadTest(); // Ensure the deployment was successful. if (tloadTestContract == address(0)) { revert TloadTestContractDeploymentFailed(); } // Determine if TSTORE is supported. bool tstoreInitialSupport = _testTload(tloadTestContract); if (tstoreInitialSupport) { // If TSTORE is supported, set functions to their versions that use // tstore/tload directly without support checks. _setTstorish = _setTstore; _getTstorish = _getTstore; _clearTstorish = _clearTstore; } else { // If TSTORE is not supported, set functions to their versions that // fallback to sstore/sload until _tstoreSupport is true. _setTstorish = _setTstorishWithSstoreFallback; _getTstorish = _getTstorishWithSloadFallback; _clearTstorish = _clearTstorishWithSstoreFallback; } _tstoreInitialSupport = tstoreInitialSupport; // Set the address of the deployed TLOAD test contract as an immutable. _tloadTestContract = tloadTestContract; } /** * @dev External function to activate TSTORE usage. Does not need to be * called if TSTORE is supported from deployment, and only needs to be * called once. Reverts if TSTORE has already been activated or if the * opcode is not available. Note that this must be called directly from * an externally-owned account to avoid potential reentrancy issues. */ function __activateTstore() external { // Ensure this function is triggered from an externally-owned account. if (msg.sender != tx.origin) { revert OnlyDirectCalls(); } // Determine if TSTORE can potentially be activated. if (_tstoreInitialSupport || _tstoreSupport) { revert TStoreAlreadyActivated(); } // Determine if TSTORE can be activated and revert if not. if (!_testTload(_tloadTestContract)) { revert TStoreNotSupported(); } // Mark TSTORE as activated. _tstoreSupport = true; } /** * @dev Private function to set a TSTORISH value. Assigned to _setTstorish * internal function variable at construction if chain has tstore support. * * @param storageSlot The slot to write the TSTORISH value to. * @param value The value to write to the given storage slot. */ function _setTstore(uint256 storageSlot, uint256 value) private { assembly { tstore(storageSlot, value) } } /** * @dev Private function to set a TSTORISH value with sstore fallback. * Assigned to _setTstorish internal function variable at construction * if chain does not have tstore support. * * @param storageSlot The slot to write the TSTORISH value to. * @param value The value to write to the given storage slot. */ function _setTstorishWithSstoreFallback(uint256 storageSlot, uint256 value) private { if (_tstoreSupport) { assembly { tstore(storageSlot, value) } } else { assembly { sstore(storageSlot, value) } } } /** * @dev Private function to read a TSTORISH value. Assigned to _getTstorish * internal function variable at construction if chain has tstore support. * * @param storageSlot The slot to read the TSTORISH value from. * * @return value The TSTORISH value at the given storage slot. */ function _getTstore( uint256 storageSlot ) private view returns (uint256 value) { assembly { value := tload(storageSlot) } } /** * @dev Private function to read a TSTORISH value with sload fallback. * Assigned to _getTstorish internal function variable at construction * if chain does not have tstore support. * * @param storageSlot The slot to read the TSTORISH value from. * * @return value The TSTORISH value at the given storage slot. */ function _getTstorishWithSloadFallback( uint256 storageSlot ) private view returns (uint256 value) { if (_tstoreSupport) { assembly { value := tload(storageSlot) } } else { assembly { value := sload(storageSlot) } } } /** * @dev Private function to clear a TSTORISH value. Assigned to _clearTstorish internal * function variable at construction if chain has tstore support. * * @param storageSlot The slot to clear the TSTORISH value for. */ function _clearTstore(uint256 storageSlot) private { assembly { tstore(storageSlot, 0) } } /** * @dev Private function to clear a TSTORISH value with sstore fallback. * Assigned to _clearTstorish internal function variable at construction * if chain does not have tstore support. * * @param storageSlot The slot to clear the TSTORISH value for. */ function _clearTstorishWithSstoreFallback(uint256 storageSlot) private { if (_tstoreSupport) { assembly { tstore(storageSlot, 0) } } else { assembly { sstore(storageSlot, 0) } } } /** * @dev Private function to deploy a test contract that utilizes TLOAD as * part of its fallback logic. */ function _prepareTloadTest() private returns (address contractAddress) { // Utilize assembly to deploy a contract testing TLOAD support. assembly { // Write the contract deployment code payload to scratch space. mstore(0, _TLOAD_TEST_PAYLOAD) // Deploy the contract. contractAddress := create( 0, _TLOAD_TEST_PAYLOAD_OFFSET, _TLOAD_TEST_PAYLOAD_LENGTH ) } } /** * @dev Private view function to determine if TSTORE/TLOAD are supported by * the current EVM implementation by attempting to call the test * contract, which utilizes TLOAD as part of its fallback logic. */ function _testTload( address tloadTestContract ) private view returns (bool ok) { // Call the test contract, which will perform a TLOAD test. If the call // does not revert, then TLOAD/TSTORE is supported. Do not forward all // available gas, as all forwarded gas will be consumed on revert. (ok, ) = tloadTestContract.staticcall{ gas: gasleft() / 10 }(""); } }
// 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 pragma solidity ^0.8.24; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { Tstorish } from "tstorish/Tstorish.sol"; import { TransferSecurityLevels } from "./interfaces/IStrictAuthorizedTransferSecurityRegistry.sol"; /// @title StrictAuthorizedTransferSecurityRegistryExtraViewFns /// @dev Additional view functions, called by StrictAuthorizedTransferSecurityRegistry /// via delegatecall in the fallback. contract StrictAuthorizedTransferSecurityRegistryExtraViewFns is Tstorish { using EnumerableSet for EnumerableSet.AddressSet; error StrictAuthorizedTransferSecurityRegistry__NotImplemented(); struct CollectionSecurityPolicy { TransferSecurityLevels transferSecurityLevel; uint120 operatorWhitelistId; uint120 permittedContractReceiversId; } struct AccountList { EnumerableSet.AddressSet enumerableAccounts; mapping (address => bool) nonEnumerableAccounts; } struct List { address owner; AccountList authorizers; AccountList operators; } struct CollectionConfiguration { uint120 listId; bool policyBypassed; bool blacklistBased; bool directTransfersDisabled; bool contractRecipientsDisabled; bool signatureRegistrationRequired; } uint120 private UNUSED_lastListId; mapping (uint120 => List) private lists; /// @dev Mapping of collection addresses to list ids & security policies. mapping (address => CollectionConfiguration) private collectionConfiguration; // view functions from other transfer security registries, included for completeness function getBlacklistedAccounts(uint120) external pure returns (address[] memory) {} function getWhitelistedAccounts(uint120 id) external view returns (address[] memory) { return lists[id].operators.enumerableAccounts.values(); } function getBlacklistedCodeHashes(uint120) external pure returns (bytes32[] memory) {} function getWhitelistedCodeHashes(uint120) external pure returns (bytes32[] memory) {} function isAccountBlacklisted(uint120, address) external pure returns (bool) { return false; } function isAccountWhitelisted(uint120 id, address account) external view returns (bool) { return lists[id].operators.nonEnumerableAccounts[account]; } function isCodeHashBlacklisted(uint120, bytes32) external pure returns (bool) { return false; } function isCodeHashWhitelisted(uint120, bytes32) external pure returns (bool) { return false; } function getBlacklistedAccountsByCollection(address) external pure returns (address[] memory) {} function getWhitelistedAccountsByCollection(address collection) external view returns (address[] memory) { return lists[collectionConfiguration[collection].listId].operators.enumerableAccounts.values(); } function getBlacklistedCodeHashesByCollection(address) external pure returns (bytes32[] memory) {} function getWhitelistedCodeHashesByCollection(address) external pure returns (bytes32[] memory) {} function isAccountBlacklistedByCollection(address, address) external pure returns (bool) { return false; } function isAccountWhitelistedByCollection( address collection, address account ) external view returns (bool) { return lists[collectionConfiguration[collection].listId].operators.nonEnumerableAccounts[account]; } function isCodeHashBlacklistedByCollection(address, bytes32) external pure returns (bool) { return false; } function isCodeHashWhitelistedByCollection(address, bytes32) external pure returns (bool) { return false; } function getCollectionSecurityPolicy( address collection ) external view returns (CollectionSecurityPolicy memory) { CollectionConfiguration memory config = collectionConfiguration[collection]; return CollectionSecurityPolicy({ transferSecurityLevel: _getSecurityLevel(config), operatorWhitelistId: config.listId, permittedContractReceiversId: 0 }); } function getWhitelistedOperators(uint120 id) external view returns (address[] memory) { return lists[id].operators.enumerableAccounts.values(); } function getPermittedContractReceivers(uint120) external pure returns (address[] memory) {} function isOperatorWhitelisted(uint120 id, address operator) external view returns (bool) { return lists[id].operators.nonEnumerableAccounts[operator]; } function isContractReceiverPermitted(uint120, address) external pure returns (bool) { return true; } function _getSecurityLevel( CollectionConfiguration memory config ) internal pure returns (TransferSecurityLevels level) { bool policyBypassed = config.policyBypassed; bool blacklistBased = config.blacklistBased; bool directTransfersDisabled = config.directTransfersDisabled; bool contractRecipientsDisabled = config.contractRecipientsDisabled; bool signatureRegistrationRequired = config.signatureRegistrationRequired; if (policyBypassed) { return TransferSecurityLevels.One; } if (blacklistBased) { return TransferSecurityLevels.Two; } if (directTransfersDisabled) { if (signatureRegistrationRequired) { return TransferSecurityLevels.Eight; } else if (contractRecipientsDisabled) { return TransferSecurityLevels.Seven; } return TransferSecurityLevels.Four; } if (signatureRegistrationRequired) { return TransferSecurityLevels.Six; } else if (contractRecipientsDisabled) { return TransferSecurityLevels.Five; } return TransferSecurityLevels.Three; } fallback() external { revert StrictAuthorizedTransferSecurityRegistry__NotImplemented(); } }
// 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 // 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 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; }
{ "remappings": [ "seaport-core/=lib/seaport-core/", "seaport-types/=lib/seaport-types/", "seaport-sol/=lib/seaport-sol/src/", "seaport-deploy/=lib/seaport-deploy/src/", "solady/=lib/solady/", "@openzeppelin/=lib/openzeppelin-contracts/", "@limitbreak/creator-token-standards/=lib/creator-token-standards/src/", "@rari-capital/solmate/=lib/seaport-sol/lib/seaport/lib/solmate/", "ERC721A/=lib/creator-token-standards/lib/ERC721A/contracts/", "creator-token-standards/=lib/creator-token-standards/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/seaport-sol/lib/seaport/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a/=lib/creator-token-standards/lib/ERC721A/", "forge-std/=lib/forge-std/src/", "murky/=lib/creator-token-standards/lib/murky/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "seaport/=lib/seaport-sol/lib/seaport/contracts/", "solarray/=lib/seaport-sol/lib/solarray/src/", "solmate/=lib/seaport-sol/lib/seaport/lib/solmate/src/", "tstorish/=lib/tstorish/src/" ], "optimizer": { "enabled": true, "runs": 9999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"defaultOwner","type":"address"},{"internalType":"address","name":"eoaRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"OnlyDirectCalls","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__ArrayLengthCannotBeZero","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__CallerDoesNotOwnList","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__CallerIsNotValidAuthorizer","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__CallerMustBeWhitelistedOperator","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__CallerMustHaveElevatedPermissionsForSpecifiedNFT","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__ListDoesNotExist","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__ListOwnershipCannotBeTransferredToZeroAddress","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__ReceiverMustNotHaveDeployedCode","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__ReceiverProofOfEOASignatureUnverified","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__UnsupportedSecurityLevel","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__UnsupportedSecurityLevelDetail","type":"error"},{"inputs":[],"name":"StrictAuthorizedTransferSecurityRegistry__ZeroAddressNotAllowed","type":"error"},{"inputs":[],"name":"TStoreAlreadyActivated","type":"error"},{"inputs":[],"name":"TStoreNotSupported","type":"error"},{"inputs":[],"name":"TloadTestContractDeploymentFailed","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":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint120","name":"id","type":"uint120"}],"name":"AppliedListToCollection","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":"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":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"}],"name":"SetTransferSecurityLevel","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"__activateTstore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"addAccountToAuthorizers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"addAccountToBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"addAccountToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"addAccountsToAuthorizers","outputs":[],"stateMutability":"nonpayable","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":"address[]","name":"accounts","type":"address[]"}],"name":"addAuthorizers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"addOperators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"afterAuthorizedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"afterAuthorizedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"afterAuthorizedTransferWithAmount","outputs":[],"stateMutability":"nonpayable","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":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"beforeAuthorizedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"beforeAuthorizedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"beforeAuthorizedTransferWithAmount","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":"uint120","name":"id","type":"uint120"}],"name":"getAuthorizerAccounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getAuthorizerAccountsByCollection","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","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":"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"},{"internalType":"address","name":"account","type":"address"}],"name":"isAccountAuthorizer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"isAccountAuthorizerOfCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"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":"id","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":"account","type":"address"}],"name":"removeAccountFromAuthorizers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"removeAccountFromBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address","name":"account","type":"address"}],"name":"removeAccountFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint120","name":"id","type":"uint120"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"removeAccountsFromAuthorizers","outputs":[],"stateMutability":"nonpayable","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"}],"name":"renounceOwnershipOfList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint8","name":"level","type":"uint8"},{"internalType":"bool","name":"enableAuthorizationMode","type":"bool"},{"internalType":"bool","name":"authorizersCanSetWildcardOperators","type":"bool"},{"internalType":"bool","name":"enableAccountFreezingMode","type":"bool"}],"name":"setTransferSecurityLevelOfCollection","outputs":[],"stateMutability":"nonpayable","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":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"validateTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"validateTransfer","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"validateTransfer","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
61016060405234801562000011575f80fd5b5060405162004d8138038062004d8183398101604081905262000034916200032c565b5f6200003f62000235565b90506001600160a01b0381166200006957604051632aea588760e01b815260040160405180910390fd5b5f62000075826200024e565b90508015620000c157620002b0602090811b62001d8d176001600160401b0390811660c052620002b7821b62001d9417811660e052620002bb90911b62001d98171661010052620000ff565b620002c1602090811b62001d9e176001600160401b0390811660c052620002d7821b62001db317811660e052620002f190911b62001dcc1716610100525b151560a0526001600160a01b039081166080525f80805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980549285166001600160a01b03199093169290921790915560405181907f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be1490620001a6906020808252600c908201526b1111519055531508131254d560a21b604082015260600190565b60405180910390a26040516001600160a01b038416906001600160781b038316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367905f90a3604051620001fa9062000307565b604051809103905ff08015801562000214573d5f803e3d5ffd5b506001600160a01b0390811661012052919091166101405250620003829050565b5f696002601e613d5c3d52f35f52600a60165ff0905090565b5f816001600160a01b0316600a5a62000268919062000362565b6040515f8181818686fa925050503d805f8114620002a2576040519150601f19603f3d011682016040523d82523d5f602084013e620002a7565b606091505b50909392505050565b80825d5050565b5c90565b5f815d50565b5f5460ff1615620002d35780825d5050565b9055565b5f805460ff1615620002e857505c90565b5080545b919050565b5f5460ff161562000302575f815d50565b5f9055565b610d07806200407a83390190565b80516001600160a01b0381168114620002ec575f80fd5b5f80604083850312156200033e575f80fd5b620003498362000315565b9150620003596020840162000315565b90509250929050565b5f826200037d57634e487b7160e01b5f52601260045260245ffd5b500490565b60805160a05160c05160e051610100516101205161014051613c67620004135f395f8181611424015281816122b2015281816126fd0152612f7a01525f61032001525f610adb01525f8181610c57015281816124040152818161283901526130cc01525f8181610c8f01528181610e0f01528181610f7c015261243801525f61116701525f6111ce0152613c675ff3fe608060405234801561000f575f80fd5b506004361061031e575f3560e01c806388c1d66d116101a5578063b8dcc68f116100ec578063ddae38f211610095578063e991dc301161006f578063e991dc30146108ec578063ede0fe31146108ff578063fd51f20f146109125761031e565b8063ddae38f214610615578063de02cbb1146108c6578063df5fd29a146108d95761031e565b8063caee23ea116100c6578063caee23ea1461088d578063da0194c0146108a0578063dda964e3146108b35761031e565b8063b8dcc68f14610854578063bf7bfd7e14610867578063c3d58f4d1461087a5761031e565b8063a1cc5cc11161014e578063b6e39ba111610128578063b6e39ba1146107d3578063b70510f5146107e6578063b89c4b0d146108415761031e565b8063a1cc5cc114610755578063a5ce71f514610755578063ae602f44146107685761031e565b80638b6ee8651161017f5780638b6ee865146106c85780638e28800f146106db578063982d03c0146107425761031e565b806388c1d66d1461068f57806389631626146106a257806389a9c855146106b55761031e565b8063317e3e8d116102695780636971082811610212578063755b6fd7116101ec578063755b6fd7146106155780637bac97de146106285780637c1e14b4146104e85761031e565b806369710828146105e75780636bfab91d146105fa5780637423eb3c1461060d5761031e565b80633e5c139d116102435780633e5c139d146105ae57806343999db8146105c157806350793315146105d45761031e565b8063317e3e8d146105215780633a0e3160146105345780633cda743a146105475761031e565b806316a17ce0116102cb578063285fb8c8116102a5578063285fb8c8146104e857806328cc1131146104fb5780632eb0b98a1461050e5761031e565b806316a17ce01461043b5780631854b2411461049657806323c99262146104a95761031e565b80630ad38899116102fc5780630ad38899146103f55780630b6153091461040857806310b5c6a01461041b5761031e565b8063015499301461035f57806301ffc9a714610372578063057497cb1461039a575b7f0000000000000000000000000000000000000000000000000000000000000000365f80375f80365f845af43d5f803e808015610359573d5ff35b3d5ffd5b005b61035d61036d36600461359c565b610925565b61038561038036600461361b565b6109d0565b60405190151581526020015b60405180910390f35b6103856103a836600461367d565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260060190915290205460ff1692915050565b61035d6104033660046136ae565b610a93565b61035d61041636600461367d565b610b05565b61042e6104293660046136c7565b610bc4565b60405161039191906136e0565b61038561044936600461367d565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260090190915290205460ff1692915050565b61035d6104a4366004613739565b610bf2565b5f546104c89061010090046effffffffffffffffffffffffffffff1681565b6040516effffffffffffffffffffffffffffff9091168152602001610391565b61035d6104f636600461378a565b610bff565b61035d6105093660046137ca565b610c0f565b61035d61051c36600461359c565b610cbe565b61035d61052f366004613807565b610d63565b61035d610542366004613877565b610dcb565b61038561055536600461389f565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526003909201909152205460ff1690565b61042e6105bc3660046136ae565b610e3a565b61035d6105cf36600461367d565b610e8b565b61035d6105e236600461389f565b610f1e565b61035d6105f536600461359c565b610fa3565b61035d61060836600461367d565b611047565b61035d61112c565b61035d61062336600461359c565b611254565b61038561063636600461389f565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526009909201909152205460ff1690565b61035d61069d36600461367d565b6112f6565b61042e6106b03660046136c7565b6113af565b6103856106c33660046136ae565b6113dd565b61035d6106d63660046136c7565b61148f565b6103856106e936600461389f565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526006909201909152205460ff1690565b61042e6107503660046136ae565b61150c565b61035d61076336600461359c565b61155d565b6107ae6107763660046136c7565b6effffffffffffffffffffffffffffff165f9081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b61035d6107e1366004613877565b611602565b6103856107f436600461367d565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260030190915290205460ff1692915050565b61035d61084f366004613877565b611647565b6104c86108623660046138fe565b61168c565b61035d61087536600461393d565b611796565b61035d61088836600461367d565b611881565b61035d61089b366004613965565b611914565b61035d6108ae3660046139ad565b611920565b61042e6108c13660046136c7565b61192a565b6104c86108d43660046139e5565b611959565b61035d6108e736600461359c565b611b26565b61042e6108fa3660046136ae565b611bc8565b61035d61090d36600461367d565b611c19565b61035d61092036600461367d565b611cd3565b8261092f81611de1565b815f81900361096a576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c168152600160205260409020600701925060029150611e4f9050565b5050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082161580610a4157507fffffffff0000000000000000000000000000000000000000000000000000000082167f751a614900000000000000000000000000000000000000000000000000000000145b80610a8d57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b610a9c81611fa6565b610b027f596a397a0000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8316175b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b50565b81610b0f81611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610b4357610b43613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f206001015f61202d565b50505050565b6effffffffffffffffffffffffffffff81165f908152600160205260409020606090610a8d9060070161211f565b6109c98585858585612132565b610c0a83838361257d565b505050565b610c1883611fa6565b7f71836d45000000000000000000000000000000000000000000000000000000005f908152601884905260048390526038812090610c798263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016565b90505f610c868483613a86565b9050610cb683827f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b505050505050565b82610cc881611de1565b815f819003610d03576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c1681526001602081905260409091206004019350915061202d9050565b821580610d6e575081155b80610d765750805b15610dad576040517f7ced84b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858560ff166008811115610dc657610dc6613a99565b6129a0565b610dd482611fa6565b7f7e746c61000000000000000000000000000000000000000000000000000000005f9081526018839052600482905260389020610e369060017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b5050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600191829052909120606091610a8d910161211f565b81610e9581611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610ec957610ec9613a2c565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526effffffffffffffffffffffffffffff85165f908152600190915260409020610bbe90859083906007016002611e4f565b610f2781611fa6565b610e367f596a397a0000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8316178373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b82610fad81611de1565b815f819003610fe8576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c16815260016020526040902060070192506002915061202d9050565b8161105181611de1565b73ffffffffffffffffffffffffffffffffffffffff821661109e576040517f2ba5f16500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff83165f8181526001602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915590519092917f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736791a3505050565b333214611165576040517f2599431400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008061119257505f5460ff165b156111c9576040517ff45b98b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111f27f0000000000000000000000000000000000000000000000000000000000000000612d08565b611228576040517f70a4078f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b8261125e81611de1565b815f819003611299576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c16815260016020819052604082200193509150611e4f9050565b8161130081611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f8151811061133457611334613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f206001015f611e4f565b6effffffffffffffffffffffffffffff81165f908152600160205260409020606090610a8d9060040161211f565b6040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f0000000000000000000000000000000000000000000000000000000000000000909116906389a9c85590602401602060405180830381865afa15801561146b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8d9190613ac6565b8061149981611de1565b6effffffffffffffffffffffffffffff82165f8181526001602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519091907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367908390a35050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff16835260019091529020606090610a8d9060070161211f565b8261156781611de1565b815f8190036115a2576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c16815260016020819052604090912060040193509150611e4f9050565b61160b82611fa6565b7f71836d45000000000000000000000000000000000000000000000000000000005f9081526018839052600482905260389020610e3690610ad9565b61165082611fa6565b7f7e746c61000000000000000000000000000000000000000000000000000000005f9081526018839052600482905260389020610e3690610ad9565b5f805f600181819054906101000a90046effffffffffffffffffffffffffffff166116b690613ae1565b82546effffffffffffffffffffffffffffff8083166101009490940a848102910219909116179092555f818152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905551919250907f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be149061174a9087908790613b0e565b60405180910390a260405133906effffffffffffffffffffffffffffff8316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367905f90a39392505050565b61179f82612d73565b5f546effffffffffffffffffffffffffffff610100909104811690821611156117f4576040517f3fbf501e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526002602052604080822080547fffffffffffffffffffffffffffffffffff000000000000000000000000000000166effffffffffffffffffffffffffffff861690811790915590519092917fa66ff5557b7dc1562bb5e83306e15b513a25aa7537369bce38fc29c20847a79191a35050565b8161188b81611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f815181106118bf576118bf613a2c565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526effffffffffffffffffffffffffffff85165f908152600190915260409020610bbe9085908390600701600261202d565b610bbe84848484612dfa565b610e3682826129a0565b6effffffffffffffffffffffffffffff81165f908152600160208190526040909120606091610a8d910161211f565b5f805f600181819054906101000a90046effffffffffffffffffffffffffffff1661198390613ae1565b91906101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff16021790559050600181036effffffffffffffffffffffffffffff16836effffffffffffffffffffffffffffff161115611a17576040517f3fbf501e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8084165f908152600160205260408082209284168083529181902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317815590519091907f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be1490611a9e908a908a90613b0e565b60405180910390a260405133906effffffffffffffffffffffffffffff8516907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367905f90a3611af55f848460010184600101613213565b611b086001848460040184600401613213565b611b1b6002848460070184600701613213565b509095945050505050565b82611b3081611de1565b815f819003611b6b576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c1681526001602081905260408220019350915061202d9050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff16835260019091529020606090610a8d9060040161211f565b81611c2381611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110611c5757611c57613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f206004016001611e4f565b81611cdd81611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110611d1157611d11613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f20600401600161202d565b80825d5050565b5c90565b5f815d50565b5f5460ff1615611daf5780825d5050565b9055565b5f805460ff1615611dc357505c90565b5080545b919050565b5f5460ff1615611ddc575f815d50565b5f9055565b6effffffffffffffffffffffffffffff81165f9081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff163314610b02576040517fd5f2492900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8451811015610cb657848181518110611e6d57611e6d613a2c565b602002602001015191505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611edc576040517f8f6e844e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ee68483613310565b15611f9e578173ffffffffffffffffffffffffffffffffffffffff16866effffffffffffffffffffffffffffff16846002811115611f2657611f26613a99565b6040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d17905f90a473ffffffffffffffffffffffffffffffffffffffff82165f908152600285016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611e52565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff1683526001825280832033845260030190915290205460ff16610b02576040517feab2f2de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8451811015610cb65784818151811061204b5761204b613a2c565b602090810291909101015191506120628483613331565b15612117578173ffffffffffffffffffffffffffffffffffffffff16866effffffffffffffffffffffffffffff168460028111156120a2576120a2613a99565b6040517f503012490a650739416858609e898957b874d17415a062945179c57357978840905f90a473ffffffffffffffffffffffffffffffffffffffff82165f908152600285016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600101612030565b60605f61212b83613352565b9392505050565b335f90815260026020908152604091829020825160c08101845290546effffffffffffffffffffffffffffff8116825260ff6f01000000000000000000000000000000820481161580159484019490945270010000000000000000000000000000000082048116151594830194909452710100000000000000000000000000000000008104841615156060830152720100000000000000000000000000000000000081048416151560808301527301000000000000000000000000000000000000009004909216151560a083015261220a57506109c9565b8060800151156122635773ffffffffffffffffffffffffffffffffffffffff84163b15612263576040517f52245b9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a0015115612351576040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000016906389a9c85590602401602060405180830381865afa1580156122f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061231b9190613ac6565b612351576040517fa451bf2a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16036123c6578060600151156123c0576040517ff87c961400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506109c9565b7f71836d45000000000000000000000000000000000000000000000000000000005f90815233601852600484905260388120906124268263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016565b90508381106124675761245f828583037f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b5050506109c9565b8260400151156124f55782516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8c16845260090190915290205460ff16156124f0576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612573565b82516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8c16845260060190915290205460ff16612573576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b335f90815260026020908152604091829020825160c08101845290546effffffffffffffffffffffffffffff8116825260ff6f01000000000000000000000000000000820481161580159484019490945270010000000000000000000000000000000082048116151594830194909452710100000000000000000000000000000000008104841615156060830152720100000000000000000000000000000000000081048416151560808301527301000000000000000000000000000000000000009004909216151560a08301526126555750505050565b8060800151156126ae5773ffffffffffffffffffffffffffffffffffffffff82163b156126ae576040517f52245b9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a001511561279c576040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f000000000000000000000000000000000000000000000000000000000000000016906389a9c85590602401602060405180830381865afa158015612742573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127669190613ac6565b61279c576040517fa451bf2a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361280b57806060015115610bbe576040517ff87c961400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b337f596a397a000000000000000000000000000000000000000000000000000000001761285b8163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612894575050505050565b8160400151156129225781516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845260090190915290205460ff161561291d576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9565b81516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845260060190915290205460ff166109c9576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129a982612d73565b5f8160088111156129bc576129bc613a99565b036129c5575060035b73ffffffffffffffffffffffffffffffffffffffff82165f90815260026020526040902060018260088111156129fd576129fd613a99565b03612a3f5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff166f01000000000000000000000000000000178155612cca565b6002826008811115612a5357612a53613a99565b03612a965780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff16700100000000000000000000000000000000178155612cca565b6003826008811115612aaa57612aaa613a99565b03612ada5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff168155612cca565b6004826008811115612aee57612aee613a99565b03612b325780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff1671010000000000000000000000000000000000178155612cca565b6005826008811115612b4657612b46613a99565b03612b8b5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff167201000000000000000000000000000000000000178155612cca565b6006826008811115612b9f57612b9f613a99565b03612be55780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff16730100000000000000000000000000000000000000178155612cca565b6007826008811115612bf957612bf9613a99565b03612c3e5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff167201010000000000000000000000000000000000178155612cca565b6008826008811115612c5257612c52613a99565b03612c985780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff16730100010000000000000000000000000000000000178155612cca565b6040517f5ec600e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb39d8f1e6f05413a407e46fc950eb92e9f5b3d65a47c3f0bdc7a2741a6ec0f7d8383604051612cfb929190613b5a565b60405180910390a1505050565b5f8173ffffffffffffffffffffffffffffffffffffffff16600a5a612d2d9190613bb9565b6040515f8181818686fa925050503d805f8114612d65576040519150601f19603f3d011682016040523d82523d5f602084013e612d6a565b606091505b50909392505050565b73ffffffffffffffffffffffffffffffffffffffff81163303612d935750565b612d9c816133ab565b73ffffffffffffffffffffffffffffffffffffffff163303612dbb5750565b612dc4816133d4565b610b02576040517f05b3336400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f90815260026020908152604091829020825160c08101845290546effffffffffffffffffffffffffffff8116825260ff6f01000000000000000000000000000000820481161580159484019490945270010000000000000000000000000000000082048116151594830194909452710100000000000000000000000000000000008104841615156060830152720100000000000000000000000000000000000081048416151560808301527301000000000000000000000000000000000000009004909216151560a0830152612ed25750610bbe565b806080015115612f2b5773ffffffffffffffffffffffffffffffffffffffff83163b15612f2b576040517f52245b9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a0015115613019576040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f000000000000000000000000000000000000000000000000000000000000000016906389a9c85590602401602060405180830381865afa158015612fbf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fe39190613ac6565b613019576040517fa451bf2a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361308e57806060015115613088576040517ff87c961400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610bbe565b7f7e746c61000000000000000000000000000000000000000000000000000000005f90815233601852600483905260388120906130ee8263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016565b905080156130fe57505050610bbe565b82604001511561318c5782516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16845260090190915290205460ff1615613187576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61320a565b82516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16845260060190915290205460ff1661320a576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b8181600281015f61322384613415565b90505f805b828110156133045761323a868261341e565b91506132468583613310565b156132fc578173ffffffffffffffffffffffffffffffffffffffff16896effffffffffffffffffffffffffffff168b600281111561328657613286613a99565b6040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d17905f90a473ffffffffffffffffffffffffffffffffffffffff82165f90815260208590526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101613228565b50505050505050505050565b5f61212b8373ffffffffffffffffffffffffffffffffffffffff8416613429565b5f61212b8373ffffffffffffffffffffffffffffffffffffffff8416613475565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561339f57602002820191905f5260205f20905b81548152602001906001019080831161338b575b50505050509050919050565b5f638da5cb5b5f5260205f6004601c855afa8060203d101516156133ce575f5191505b50919050565b5f604051606081016040526391d1485481525f816020015233816040015260205f6044601c8401865afa90508060203d101516156133ce5750505f51919050565b5f610a8d825490565b5f61212b8383613558565b5f81815260018301602052604081205461346e57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610a8d565b505f610a8d565b5f818152600183016020526040812054801561354f575f613497600183613bf1565b85549091505f906134aa90600190613bf1565b9050818114613509575f865f0182815481106134c8576134c8613a2c565b905f5260205f200154905080875f0184815481106134e8576134e8613a2c565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061351a5761351a613c04565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610a8d565b5f915050610a8d565b5f825f01828154811061356d5761356d613a2c565b905f5260205f200154905092915050565b80356effffffffffffffffffffffffffffff81168114611dc7575f80fd5b5f805f604084860312156135ae575f80fd5b6135b78461357e565b9250602084013567ffffffffffffffff808211156135d3575f80fd5b818601915086601f8301126135e6575f80fd5b8135818111156135f4575f80fd5b8760208260051b8501011115613608575f80fd5b6020830194508093505050509250925092565b5f6020828403121561362b575f80fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461212b575f80fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114611dc7575f80fd5b5f806040838503121561368e575f80fd5b6136978361357e565b91506136a56020840161365a565b90509250929050565b5f602082840312156136be575f80fd5b61212b8261365a565b5f602082840312156136d7575f80fd5b61212b8261357e565b602080825282518282018190525f9190848201906040850190845b8181101561372d57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016136fb565b50909695505050505050565b5f805f805f60a0868803121561374d575f80fd5b6137568661365a565b94506137646020870161365a565b93506137726040870161365a565b94979396509394606081013594506080013592915050565b5f805f6060848603121561379c575f80fd5b6137a58461365a565b92506137b36020850161365a565b91506137c16040850161365a565b90509250925092565b5f805f606084860312156137dc575f80fd5b6137e58461365a565b95602085013595506040909401359392505050565b8015158114610b02575f80fd5b5f805f805f60a0868803121561381b575f80fd5b6138248661365a565b9450602086013560ff81168114613839575f80fd5b93506040860135613849816137fa565b92506060860135613859816137fa565b91506080860135613869816137fa565b809150509295509295909350565b5f8060408385031215613888575f80fd5b6138918361365a565b946020939093013593505050565b5f80604083850312156138b0575f80fd5b6136978361365a565b5f8083601f8401126138c9575f80fd5b50813567ffffffffffffffff8111156138e0575f80fd5b6020830191508360208285010111156138f7575f80fd5b9250929050565b5f806020838503121561390f575f80fd5b823567ffffffffffffffff811115613925575f80fd5b613931858286016138b9565b90969095509350505050565b5f806040838503121561394e575f80fd5b6139578361365a565b91506136a56020840161357e565b5f805f8060808587031215613978575f80fd5b6139818561365a565b935061398f6020860161365a565b925061399d6040860161365a565b9396929550929360600135925050565b5f80604083850312156139be575f80fd5b6139c78361365a565b91506020830135600981106139da575f80fd5b809150509250929050565b5f805f604084860312156139f7575f80fd5b833567ffffffffffffffff811115613a0d575f80fd5b613a19868287016138b9565b90945092506137c190506020850161357e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610a8d57610a8d613a59565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f60208284031215613ad6575f80fd5b815161212b816137fa565b5f6effffffffffffffffffffffffffffff808316818103613b0457613b04613a59565b6001019392505050565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b73ffffffffffffffffffffffffffffffffffffffff831681526040810160098310613bac577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8260208301529392505050565b5f82613bec577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610a8d57610a8d613a59565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea2646970667358221220160996c94b1d698a40469e3f97911dd81a027efec7d78941305ede91222dd7d864736f6c6343000818003361012060405234801562000011575f80fd5b505f6200001d620000f4565b90506001600160a01b0381166200004757604051632aea588760e01b815260040160405180910390fd5b5f62000053826200010d565b905080156200009f576200016f602090811b62000678176001600160401b0390811660c05262000176821b6200067f17811660e0526200017a90911b62000683171661010052620000dd565b62000180602090811b62000689176001600160401b0390811660c05262000196821b6200069e17811660e052620001ac90911b620006b71716610100525b151560a0526001600160a01b0316608052620001e2565b5f696002601e613d5c3d52f35f52600a60165ff0905090565b5f816001600160a01b0316600a5a620001279190620001c2565b6040515f8181818686fa925050503d805f811462000161576040519150601f19603f3d011682016040523d82523d5f602084013e62000166565b606091505b50909392505050565b80825d5050565b5c90565b5f815d50565b5f5460ff1615620001925780825d5050565b9055565b5f805460ff1615620001a757505c90565b505490565b5f5460ff1615620001bd575f815d50565b5f9055565b5f82620001dd57634e487b7160e01b5f52601260045260245ffd5b500490565b60805160a05160c05160e05161010051610af0620002175f395f50505f50505f50505f6103f501525f61045c0152610af05ff3fe608060405234801561000f575f80fd5b5060043610610180575f3560e01c80637bac97de116100d6578063982d03c01161008a578063d415f62f11610064578063d415f62f146102a2578063d72dde5e146101b2578063e991dc301461037357610180565b8063982d03c014610345578063b67d8f9914610273578063b95545521461035357610180565b80638e28800f116100bb5780638e28800f146102c85780639340a7cc146102585780639445f5301461032f57610180565b80637bac97de146102ba578063896316261461028157610180565b80632c7fe70a116101385780635e17263d116101125780635e17263d146102a25780637161ac8d146102945780637423eb3c146102b057610180565b80632c7fe70a146102735780633fe5df99146102815780634c9d0b451461029457610180565b806316a17ce01161016957806316a17ce01461024357806316f18d741461025857806317e94a6c1461022257610180565b8063057497cb146101b257806310b5c6a014610222575b6040517f89452af100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61020d6101c0366004610895565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260060190915290205460ff1692915050565b60405190151581526020015b60405180910390f35b6102366102303660046108c6565b50606090565b60405161021991906108df565b61020d610251366004610895565b5f92915050565b610266610230366004610938565b6040516102199190610951565b61020d610251366004610988565b61023661028f3660046108c6565b610386565b6102666102303660046108c6565b61020d6102513660046109b0565b6102b86103ba565b005b61020d6102513660046109ca565b61020d6102d63660046109ca565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526006909201909152205460ff1690565b61020d61033d366004610895565b600192915050565b610236610230366004610938565b610366610361366004610938565b6104e2565b6040516102199190610a11565b610236610381366004610938565b610627565b6effffffffffffffffffffffffffffff81165f9081526001602052604090206060906103b4906004016106cc565b92915050565b3332146103f3576040517f2599431400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008061042057505f5460ff165b15610457576040517ff45b98b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104807f00000000000000000000000000000000000000000000000000000000000000006106df565b6104b6576040517f70a4078f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60408051606080820183525f808352602080840182905283850182905273ffffffffffffffffffffffffffffffffffffffff861682526002815290849020845160c08101865290546effffffffffffffffffffffffffffff8116825260ff6f0100000000000000000000000000000082048116151593830193909352700100000000000000000000000000000000810483161515828701527101000000000000000000000000000000000081048316151582850152720100000000000000000000000000000000000081048316151560808301527301000000000000000000000000000000000000009004909116151560a08201528351918201909352909190806105ec8361074a565b60088111156105fd576105fd6109e4565b815291516effffffffffffffffffffffffffffff1660208301525f60409092019190915292915050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600190915290206060906103b4906004016106cc565b80825d5050565b5c90565b5f815d50565b5f5460ff161561069a5780825d5050565b9055565b5f805460ff16156106ae57505c90565b5080545b919050565b5f5460ff16156106c7575f815d50565b5f9055565b60605f6106d8836107fb565b9392505050565b5f8173ffffffffffffffffffffffffffffffffffffffff16600a5a6107049190610a82565b6040515f8181818686fa925050503d805f811461073c576040519150601f19603f3d011682016040523d82523d5f602084013e610741565b606091505b50909392505050565b602081015160408201516060830151608084015160a08501515f9493929190841561077c575060019695505050505050565b831561078f575060029695505050505050565b82156107c85780156107a8575060089695505050505050565b81156107bb575060079695505050505050565b5060049695505050505050565b80156107db575060069695505050505050565b81156107ee575060059695505050505050565b5060039695505050505050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561084857602002820191905f5260205f20905b815481526020019060010190808311610834575b50505050509050919050565b80356effffffffffffffffffffffffffffff811681146106b2575f80fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146106b2575f80fd5b5f80604083850312156108a6575f80fd5b6108af83610854565b91506108bd60208401610872565b90509250929050565b5f602082840312156108d6575f80fd5b6106d882610854565b602080825282518282018190525f9190848201906040850190845b8181101561092c57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016108fa565b50909695505050505050565b5f60208284031215610948575f80fd5b6106d882610872565b602080825282518282018190525f9190848201906040850190845b8181101561092c5783518352928401929184019160010161096c565b5f8060408385031215610999575f80fd5b6109a283610872565b946020939093013593505050565b5f80604083850312156109c1575f80fd5b6109a283610854565b5f80604083850312156109db575f80fd5b6108af83610872565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8151606082019060098110610a4d577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8083525060208301516effffffffffffffffffffffffffffff8082166020850152806040860151166040850152505092915050565b5f82610ab5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b50049056fea2646970667358221220c104b63905a188c6b1e795f6018b36d9c876d6bd4f6ea96593fb37a009e87c1c64736f6c634300081800330000000000000000000000000000000000a1793068b5b7e278de7c641e9e75c8000000000000000000000000721c00182a990771244d7a71b9fa2ea789a3b433
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061031e575f3560e01c806388c1d66d116101a5578063b8dcc68f116100ec578063ddae38f211610095578063e991dc301161006f578063e991dc30146108ec578063ede0fe31146108ff578063fd51f20f146109125761031e565b8063ddae38f214610615578063de02cbb1146108c6578063df5fd29a146108d95761031e565b8063caee23ea116100c6578063caee23ea1461088d578063da0194c0146108a0578063dda964e3146108b35761031e565b8063b8dcc68f14610854578063bf7bfd7e14610867578063c3d58f4d1461087a5761031e565b8063a1cc5cc11161014e578063b6e39ba111610128578063b6e39ba1146107d3578063b70510f5146107e6578063b89c4b0d146108415761031e565b8063a1cc5cc114610755578063a5ce71f514610755578063ae602f44146107685761031e565b80638b6ee8651161017f5780638b6ee865146106c85780638e28800f146106db578063982d03c0146107425761031e565b806388c1d66d1461068f57806389631626146106a257806389a9c855146106b55761031e565b8063317e3e8d116102695780636971082811610212578063755b6fd7116101ec578063755b6fd7146106155780637bac97de146106285780637c1e14b4146104e85761031e565b806369710828146105e75780636bfab91d146105fa5780637423eb3c1461060d5761031e565b80633e5c139d116102435780633e5c139d146105ae57806343999db8146105c157806350793315146105d45761031e565b8063317e3e8d146105215780633a0e3160146105345780633cda743a146105475761031e565b806316a17ce0116102cb578063285fb8c8116102a5578063285fb8c8146104e857806328cc1131146104fb5780632eb0b98a1461050e5761031e565b806316a17ce01461043b5780631854b2411461049657806323c99262146104a95761031e565b80630ad38899116102fc5780630ad38899146103f55780630b6153091461040857806310b5c6a01461041b5761031e565b8063015499301461035f57806301ffc9a714610372578063057497cb1461039a575b7f0000000000000000000000001fca38fd099c7701b4f28fbc3f0ba57ed4067137365f80375f80365f845af43d5f803e808015610359573d5ff35b3d5ffd5b005b61035d61036d36600461359c565b610925565b61038561038036600461361b565b6109d0565b60405190151581526020015b60405180910390f35b6103856103a836600461367d565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260060190915290205460ff1692915050565b61035d6104033660046136ae565b610a93565b61035d61041636600461367d565b610b05565b61042e6104293660046136c7565b610bc4565b60405161039191906136e0565b61038561044936600461367d565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260090190915290205460ff1692915050565b61035d6104a4366004613739565b610bf2565b5f546104c89061010090046effffffffffffffffffffffffffffff1681565b6040516effffffffffffffffffffffffffffff9091168152602001610391565b61035d6104f636600461378a565b610bff565b61035d6105093660046137ca565b610c0f565b61035d61051c36600461359c565b610cbe565b61035d61052f366004613807565b610d63565b61035d610542366004613877565b610dcb565b61038561055536600461389f565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526003909201909152205460ff1690565b61042e6105bc3660046136ae565b610e3a565b61035d6105cf36600461367d565b610e8b565b61035d6105e236600461389f565b610f1e565b61035d6105f536600461359c565b610fa3565b61035d61060836600461367d565b611047565b61035d61112c565b61035d61062336600461359c565b611254565b61038561063636600461389f565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526009909201909152205460ff1690565b61035d61069d36600461367d565b6112f6565b61042e6106b03660046136c7565b6113af565b6103856106c33660046136ae565b6113dd565b61035d6106d63660046136c7565b61148f565b6103856106e936600461389f565b73ffffffffffffffffffffffffffffffffffffffff9182165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600182528083209390941682526006909201909152205460ff1690565b61042e6107503660046136ae565b61150c565b61035d61076336600461359c565b61155d565b6107ae6107763660046136c7565b6effffffffffffffffffffffffffffff165f9081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b61035d6107e1366004613877565b611602565b6103856107f436600461367d565b6effffffffffffffffffffffffffffff82165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260030190915290205460ff1692915050565b61035d61084f366004613877565b611647565b6104c86108623660046138fe565b61168c565b61035d61087536600461393d565b611796565b61035d61088836600461367d565b611881565b61035d61089b366004613965565b611914565b61035d6108ae3660046139ad565b611920565b61042e6108c13660046136c7565b61192a565b6104c86108d43660046139e5565b611959565b61035d6108e736600461359c565b611b26565b61042e6108fa3660046136ae565b611bc8565b61035d61090d36600461367d565b611c19565b61035d61092036600461367d565b611cd3565b8261092f81611de1565b815f81900361096a576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c168152600160205260409020600701925060029150611e4f9050565b5050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082161580610a4157507fffffffff0000000000000000000000000000000000000000000000000000000082167f751a614900000000000000000000000000000000000000000000000000000000145b80610a8d57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b610a9c81611fa6565b610b027f596a397a0000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8316175b7f000000000000000000000000000000000000000000000000000002bb00001d9863ffffffff16565b50565b81610b0f81611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610b4357610b43613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f206001015f61202d565b50505050565b6effffffffffffffffffffffffffffff81165f908152600160205260409020606090610a8d9060070161211f565b6109c98585858585612132565b610c0a83838361257d565b505050565b610c1883611fa6565b7f71836d45000000000000000000000000000000000000000000000000000000005f908152601884905260048390526038812090610c798263ffffffff7f000000000000000000000000000000000000000000000000000002b700001d9416565b90505f610c868483613a86565b9050610cb683827f000000000000000000000000000000000000000000000000000002b000001d8d63ffffffff16565b505050505050565b82610cc881611de1565b815f819003610d03576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c1681526001602081905260409091206004019350915061202d9050565b821580610d6e575081155b80610d765750805b15610dad576040517f7ced84b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858560ff166008811115610dc657610dc6613a99565b6129a0565b610dd482611fa6565b7f7e746c61000000000000000000000000000000000000000000000000000000005f9081526018839052600482905260389020610e369060017f000000000000000000000000000000000000000000000000000002b000001d8d63ffffffff16565b5050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff168352600191829052909120606091610a8d910161211f565b81610e9581611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610ec957610ec9613a2c565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526effffffffffffffffffffffffffffff85165f908152600190915260409020610bbe90859083906007016002611e4f565b610f2781611fa6565b610e367f596a397a0000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8316178373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000002b000001d8d63ffffffff16565b82610fad81611de1565b815f819003610fe8576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c16815260016020526040902060070192506002915061202d9050565b8161105181611de1565b73ffffffffffffffffffffffffffffffffffffffff821661109e576040517f2ba5f16500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff83165f8181526001602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915590519092917f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e2736791a3505050565b333214611165576040517f2599431400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000018061119257505f5460ff165b156111c9576040517ff45b98b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111f27f000000000000000000000000bb0bffd7f8ef12ecaa0435aef8a7bd522798251c612d08565b611228576040517f70a4078f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b8261125e81611de1565b815f819003611299576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c16815260016020819052604082200193509150611e4f9050565b8161130081611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f8151811061133457611334613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f206001015f611e4f565b6effffffffffffffffffffffffffffff81165f908152600160205260409020606090610a8d9060040161211f565b6040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f000000000000000000000000721c00182a990771244d7a71b9fa2ea789a3b433909116906389a9c85590602401602060405180830381865afa15801561146b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8d9190613ac6565b8061149981611de1565b6effffffffffffffffffffffffffffff82165f8181526001602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519091907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367908390a35050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff16835260019091529020606090610a8d9060070161211f565b8261156781611de1565b815f8190036115a2576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c16815260016020819052604090912060040193509150611e4f9050565b61160b82611fa6565b7f71836d45000000000000000000000000000000000000000000000000000000005f9081526018839052600482905260389020610e3690610ad9565b61165082611fa6565b7f7e746c61000000000000000000000000000000000000000000000000000000005f9081526018839052600482905260389020610e3690610ad9565b5f805f600181819054906101000a90046effffffffffffffffffffffffffffff166116b690613ae1565b82546effffffffffffffffffffffffffffff8083166101009490940a848102910219909116179092555f818152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905551919250907f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be149061174a9087908790613b0e565b60405180910390a260405133906effffffffffffffffffffffffffffff8316907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367905f90a39392505050565b61179f82612d73565b5f546effffffffffffffffffffffffffffff610100909104811690821611156117f4576040517f3fbf501e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526002602052604080822080547fffffffffffffffffffffffffffffffffff000000000000000000000000000000166effffffffffffffffffffffffffffff861690811790915590519092917fa66ff5557b7dc1562bb5e83306e15b513a25aa7537369bce38fc29c20847a79191a35050565b8161188b81611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f815181106118bf576118bf613a2c565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526effffffffffffffffffffffffffffff85165f908152600190915260409020610bbe9085908390600701600261202d565b610bbe84848484612dfa565b610e3682826129a0565b6effffffffffffffffffffffffffffff81165f908152600160208190526040909120606091610a8d910161211f565b5f805f600181819054906101000a90046effffffffffffffffffffffffffffff1661198390613ae1565b91906101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff16021790559050600181036effffffffffffffffffffffffffffff16836effffffffffffffffffffffffffffff161115611a17576040517f3fbf501e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6effffffffffffffffffffffffffffff8084165f908152600160205260408082209284168083529181902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317815590519091907f5cc365f89543268cb9f25c255f7f610e9147e733c589bc2732279575f125be1490611a9e908a908a90613b0e565b60405180910390a260405133906effffffffffffffffffffffffffffff8516907f9b0894203394c3cbb23140db7a23b224d3e18e0366e9f65bd9c8402650e27367905f90a3611af55f848460010184600101613213565b611b086001848460040184600401613213565b611b1b6002848460070184600701613213565b509095945050505050565b82611b3081611de1565b815f819003611b6b576040517f693f369c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9858585808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052506effffffffffffffffffffffffffffff8c1681526001602081905260408220019350915061202d9050565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff16835260019091529020606090610a8d9060040161211f565b81611c2381611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110611c5757611c57613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f206004016001611e4f565b81611cdd81611de1565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110611d1157611d11613a2c565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610bbe848260015f886effffffffffffffffffffffffffffff166effffffffffffffffffffffffffffff1681526020019081526020015f20600401600161202d565b80825d5050565b5c90565b5f815d50565b5f5460ff1615611daf5780825d5050565b9055565b5f805460ff1615611dc357505c90565b5080545b919050565b5f5460ff1615611ddc575f815d50565b5f9055565b6effffffffffffffffffffffffffffff81165f9081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff163314610b02576040517fd5f2492900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8451811015610cb657848181518110611e6d57611e6d613a2c565b602002602001015191505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611edc576040517f8f6e844e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ee68483613310565b15611f9e578173ffffffffffffffffffffffffffffffffffffffff16866effffffffffffffffffffffffffffff16846002811115611f2657611f26613a99565b6040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d17905f90a473ffffffffffffffffffffffffffffffffffffffff82165f908152600285016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101611e52565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600260209081526040808320546effffffffffffffffffffffffffffff1683526001825280832033845260030190915290205460ff16610b02576040517feab2f2de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8451811015610cb65784818151811061204b5761204b613a2c565b602090810291909101015191506120628483613331565b15612117578173ffffffffffffffffffffffffffffffffffffffff16866effffffffffffffffffffffffffffff168460028111156120a2576120a2613a99565b6040517f503012490a650739416858609e898957b874d17415a062945179c57357978840905f90a473ffffffffffffffffffffffffffffffffffffffff82165f908152600285016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600101612030565b60605f61212b83613352565b9392505050565b335f90815260026020908152604091829020825160c08101845290546effffffffffffffffffffffffffffff8116825260ff6f01000000000000000000000000000000820481161580159484019490945270010000000000000000000000000000000082048116151594830194909452710100000000000000000000000000000000008104841615156060830152720100000000000000000000000000000000000081048416151560808301527301000000000000000000000000000000000000009004909216151560a083015261220a57506109c9565b8060800151156122635773ffffffffffffffffffffffffffffffffffffffff84163b15612263576040517f52245b9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a0015115612351576040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000721c00182a990771244d7a71b9fa2ea789a3b43316906389a9c85590602401602060405180830381865afa1580156122f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061231b9190613ac6565b612351576040517fa451bf2a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16036123c6578060600151156123c0576040517ff87c961400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506109c9565b7f71836d45000000000000000000000000000000000000000000000000000000005f90815233601852600484905260388120906124268263ffffffff7f000000000000000000000000000000000000000000000000000002b700001d9416565b90508381106124675761245f828583037f000000000000000000000000000000000000000000000000000002b000001d8d63ffffffff16565b5050506109c9565b8260400151156124f55782516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8c16845260090190915290205460ff16156124f0576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612573565b82516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8c16845260060190915290205460ff16612573576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b335f90815260026020908152604091829020825160c08101845290546effffffffffffffffffffffffffffff8116825260ff6f01000000000000000000000000000000820481161580159484019490945270010000000000000000000000000000000082048116151594830194909452710100000000000000000000000000000000008104841615156060830152720100000000000000000000000000000000000081048416151560808301527301000000000000000000000000000000000000009004909216151560a08301526126555750505050565b8060800151156126ae5773ffffffffffffffffffffffffffffffffffffffff82163b156126ae576040517f52245b9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a001511561279c576040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f000000000000000000000000721c00182a990771244d7a71b9fa2ea789a3b43316906389a9c85590602401602060405180830381865afa158015612742573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127669190613ac6565b61279c576040517fa451bf2a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361280b57806060015115610bbe576040517ff87c961400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b337f596a397a000000000000000000000000000000000000000000000000000000001761285b8163ffffffff7f000000000000000000000000000000000000000000000000000002b700001d9416565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612894575050505050565b8160400151156129225781516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845260090190915290205460ff161561291d576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c9565b81516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845260060190915290205460ff166109c9576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129a982612d73565b5f8160088111156129bc576129bc613a99565b036129c5575060035b73ffffffffffffffffffffffffffffffffffffffff82165f90815260026020526040902060018260088111156129fd576129fd613a99565b03612a3f5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff166f01000000000000000000000000000000178155612cca565b6002826008811115612a5357612a53613a99565b03612a965780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff16700100000000000000000000000000000000178155612cca565b6003826008811115612aaa57612aaa613a99565b03612ada5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff168155612cca565b6004826008811115612aee57612aee613a99565b03612b325780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff1671010000000000000000000000000000000000178155612cca565b6005826008811115612b4657612b46613a99565b03612b8b5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff167201000000000000000000000000000000000000178155612cca565b6006826008811115612b9f57612b9f613a99565b03612be55780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff16730100000000000000000000000000000000000000178155612cca565b6007826008811115612bf957612bf9613a99565b03612c3e5780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff167201010000000000000000000000000000000000178155612cca565b6008826008811115612c5257612c52613a99565b03612c985780547fffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffff16730100010000000000000000000000000000000000178155612cca565b6040517f5ec600e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb39d8f1e6f05413a407e46fc950eb92e9f5b3d65a47c3f0bdc7a2741a6ec0f7d8383604051612cfb929190613b5a565b60405180910390a1505050565b5f8173ffffffffffffffffffffffffffffffffffffffff16600a5a612d2d9190613bb9565b6040515f8181818686fa925050503d805f8114612d65576040519150601f19603f3d011682016040523d82523d5f602084013e612d6a565b606091505b50909392505050565b73ffffffffffffffffffffffffffffffffffffffff81163303612d935750565b612d9c816133ab565b73ffffffffffffffffffffffffffffffffffffffff163303612dbb5750565b612dc4816133d4565b610b02576040517f05b3336400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f90815260026020908152604091829020825160c08101845290546effffffffffffffffffffffffffffff8116825260ff6f01000000000000000000000000000000820481161580159484019490945270010000000000000000000000000000000082048116151594830194909452710100000000000000000000000000000000008104841615156060830152720100000000000000000000000000000000000081048416151560808301527301000000000000000000000000000000000000009004909216151560a0830152612ed25750610bbe565b806080015115612f2b5773ffffffffffffffffffffffffffffffffffffffff83163b15612f2b576040517f52245b9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a0015115613019576040517f89a9c85500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f000000000000000000000000721c00182a990771244d7a71b9fa2ea789a3b43316906389a9c85590602401602060405180830381865afa158015612fbf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fe39190613ac6565b613019576040517fa451bf2a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361308e57806060015115613088576040517ff87c961400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610bbe565b7f7e746c61000000000000000000000000000000000000000000000000000000005f90815233601852600483905260388120906130ee8263ffffffff7f000000000000000000000000000000000000000000000000000002b700001d9416565b905080156130fe57505050610bbe565b82604001511561318c5782516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16845260090190915290205460ff1615613187576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61320a565b82516effffffffffffffffffffffffffffff165f90815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16845260060190915290205460ff1661320a576040517f1de5204e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b8181600281015f61322384613415565b90505f805b828110156133045761323a868261341e565b91506132468583613310565b156132fc578173ffffffffffffffffffffffffffffffffffffffff16896effffffffffffffffffffffffffffff168b600281111561328657613286613a99565b6040517fda8f3bd170446760f0f965a9b52bf271cb9679b5e0a70059eff2d49425229d17905f90a473ffffffffffffffffffffffffffffffffffffffff82165f90815260208590526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b600101613228565b50505050505050505050565b5f61212b8373ffffffffffffffffffffffffffffffffffffffff8416613429565b5f61212b8373ffffffffffffffffffffffffffffffffffffffff8416613475565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561339f57602002820191905f5260205f20905b81548152602001906001019080831161338b575b50505050509050919050565b5f638da5cb5b5f5260205f6004601c855afa8060203d101516156133ce575f5191505b50919050565b5f604051606081016040526391d1485481525f816020015233816040015260205f6044601c8401865afa90508060203d101516156133ce5750505f51919050565b5f610a8d825490565b5f61212b8383613558565b5f81815260018301602052604081205461346e57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610a8d565b505f610a8d565b5f818152600183016020526040812054801561354f575f613497600183613bf1565b85549091505f906134aa90600190613bf1565b9050818114613509575f865f0182815481106134c8576134c8613a2c565b905f5260205f200154905080875f0184815481106134e8576134e8613a2c565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061351a5761351a613c04565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610a8d565b5f915050610a8d565b5f825f01828154811061356d5761356d613a2c565b905f5260205f200154905092915050565b80356effffffffffffffffffffffffffffff81168114611dc7575f80fd5b5f805f604084860312156135ae575f80fd5b6135b78461357e565b9250602084013567ffffffffffffffff808211156135d3575f80fd5b818601915086601f8301126135e6575f80fd5b8135818111156135f4575f80fd5b8760208260051b8501011115613608575f80fd5b6020830194508093505050509250925092565b5f6020828403121561362b575f80fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461212b575f80fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114611dc7575f80fd5b5f806040838503121561368e575f80fd5b6136978361357e565b91506136a56020840161365a565b90509250929050565b5f602082840312156136be575f80fd5b61212b8261365a565b5f602082840312156136d7575f80fd5b61212b8261357e565b602080825282518282018190525f9190848201906040850190845b8181101561372d57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016136fb565b50909695505050505050565b5f805f805f60a0868803121561374d575f80fd5b6137568661365a565b94506137646020870161365a565b93506137726040870161365a565b94979396509394606081013594506080013592915050565b5f805f6060848603121561379c575f80fd5b6137a58461365a565b92506137b36020850161365a565b91506137c16040850161365a565b90509250925092565b5f805f606084860312156137dc575f80fd5b6137e58461365a565b95602085013595506040909401359392505050565b8015158114610b02575f80fd5b5f805f805f60a0868803121561381b575f80fd5b6138248661365a565b9450602086013560ff81168114613839575f80fd5b93506040860135613849816137fa565b92506060860135613859816137fa565b91506080860135613869816137fa565b809150509295509295909350565b5f8060408385031215613888575f80fd5b6138918361365a565b946020939093013593505050565b5f80604083850312156138b0575f80fd5b6136978361365a565b5f8083601f8401126138c9575f80fd5b50813567ffffffffffffffff8111156138e0575f80fd5b6020830191508360208285010111156138f7575f80fd5b9250929050565b5f806020838503121561390f575f80fd5b823567ffffffffffffffff811115613925575f80fd5b613931858286016138b9565b90969095509350505050565b5f806040838503121561394e575f80fd5b6139578361365a565b91506136a56020840161357e565b5f805f8060808587031215613978575f80fd5b6139818561365a565b935061398f6020860161365a565b925061399d6040860161365a565b9396929550929360600135925050565b5f80604083850312156139be575f80fd5b6139c78361365a565b91506020830135600981106139da575f80fd5b809150509250929050565b5f805f604084860312156139f7575f80fd5b833567ffffffffffffffff811115613a0d575f80fd5b613a19868287016138b9565b90945092506137c190506020850161357e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610a8d57610a8d613a59565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f60208284031215613ad6575f80fd5b815161212b816137fa565b5f6effffffffffffffffffffffffffffff808316818103613b0457613b04613a59565b6001019392505050565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b73ffffffffffffffffffffffffffffffffffffffff831681526040810160098310613bac577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8260208301529392505050565b5f82613bec577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610a8d57610a8d613a59565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea2646970667358221220160996c94b1d698a40469e3f97911dd81a027efec7d78941305ede91222dd7d864736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000a1793068B5b7e278dE7c641E9E75C8000000000000000000000000721C00182a990771244d7A71B9FA2ea789A3b433
-----Decoded View---------------
Arg [0] : defaultOwner (address): 0x0000000000a1793068B5b7e278dE7c641E9E75C8
Arg [1] : eoaRegistry (address): 0x721C00182a990771244d7A71B9FA2ea789A3b433
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000a1793068B5b7e278dE7c641E9E75C8
Arg [1] : 000000000000000000000000721C00182a990771244d7A71B9FA2ea789A3b433
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.