Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 9343963 | 339 days ago | Contract Creation | 0 ETH | |||
| 9343963 | 339 days ago | Contract Creation | 0 ETH | |||
| 9343963 | 339 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
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
Contract ABI
API[{"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
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.