Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639.935 EPSAPI
Holders
450
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 3 Decimals)
Balance
115792089237316195423570985008687907853... EPSAPIValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
EPSDelegationRegister
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: CC0-1.0 // EPS Contracts v2.0.0 // www.eternalproxy.com /** @dev EPS Delegation Register. Features include: * Primary, Secondary and Rental delegation classes. * Primary and Rental: only one delegation per global / collection / token / usage type combination. * Secondary: unlimited delegations (useful for many use cases, including consolidation). * Filter returned address lists to include only primary delegations, or include secondary and rental classes * All delegations of primary and rental class are checked to ensure they are unique. * Sub-delegation. * A sub-delegate can add new delegations for the cold wallet. The internal delegation framework forms a structured auth model. * Consolidation. * Through matching secondary delegations (0xA to 0xB and 0xB to 0xA) we consolidate the usages for two addresses together. * Revoke from hot and cold in 0(1) time. * Revoke for all. * Both hot and cold can revoke for all with minimal gas (about 40k). * Multiple usages per delegation * Each delegation can have 1 to 25 usages, all stored in a single slot. * Multiple collection delegations per call * A single delegation call can set up delegations for n collections. * Structured ‘Delegation Report’ by address * For hot and cold wallets * Delegation locking * Set by the hot address, can be time bound or not * Hot addresses can unlock for a time period (e.g. unlock for the next five minutes). The lock automatically reinstates, no call or gas required. * Delegation lock bypass list * A hot wallet can load a list of addresses that can bypass the lock. For example, they can lock but add that 0xC can bypass the lock * Default descriptions for usage codes * Project specific descriptions for usage codes that can be set by admin or collection owners * Contract uses sub-delegation and delegation as its own internal auth model, allowing a structured approach to multi-user admin. * beneficiaryOf function: return the beneficiary of a token given a usage code * beneficiaryBalanceOf function: return the beneficiary balance for an address. * Both of the above can be filtered to include primary, secondary or rental delegation classes. * A useful method: beneficiaryBalanceOf for just primary classes is a very simple API for projects to implement * Headless protocol can: * Make a global delegation for any or all usage types * Make a collection specific delegation for any or all usage types * Revoke from hot * Revoke from cold * Revoke a token delegation * Revoke all for hot * Revoke all for cold * Lock a hot wallet * Unlock a hot wallet * Many view functions, including: * All addresses for a hot wallet, filtered by primary, secondary, rental * Address lock details * Validity status for a delegation * Whether a delegation from / to an address exists * All delegation keys for a hot or cold address (each delegation has a unique key which is the first 20 bytes of the hash of the delegation arguments) * If a cold or hot delegation exists for an address (in 0(1) time). */ // Usage list: // 1) All // 2) Minting / Allowlist // 3) Airdrops // 4) Voting / Governance // 5) Avatar Display // 6) Social Media // 7) Physical Events Access // 8) Virtual Events Access // 9) Club / Community Access // 10) Metaverse Access // 11) Metaverse Land // 12) Gameplay // 13) IP Licensing // 14) Sub-delegation // 15) Merch / Digital Assets // 16) -- currently vacant // 17) -- currently vacant // 18) -- currently vacant // 19) -- currently vacant // 20) -- currently vacant // 21) -- currently vacant // 22) -- currently vacant // 23) -- community reserved // 24) -- community reserved // 25) -- community reserved pragma solidity 0.8.17; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "./IEPSDelegationRegister.sol"; import "../Utils/ENSReverseRegistrar.sol"; contract EPSDelegationRegister is Context, IEPSDelegationRegister, IERCOmnReceiver { using EnumerableSet for EnumerableSet.AddressSet; // ====================================================== // CONSTANTS // ====================================================== // Delegation Scopes control integers: uint96 private constant COLLECTION_DELEGATION = 1 * (10**27); uint96 private constant TOKEN_DELEGATION = 2 * (10**27); // Delegation Classes control integers: uint96 private constant TIME_BASED_DELEGATION = 1 * (10**26); uint96 private constant SECONDARY_DELEGATION = 1 * (10**25); uint96 private constant RENTAL_DELEGATION = 2 * (10**25); // Number of positions in the control integer: uint256 private constant LENGTH_OF_CONTROL_INTEGER = 29; // Number of usage types: uint256 private constant NUMBER_OF_USAGE_TYPES = 25; // Token API call transaction types: uint256 private constant MAKE_PRIMARY_DELEGATION = 1; uint256 private constant REVOKE = 2; uint256 private constant REVOKE_ALL_FOR_HOT = 3; uint256 private constant REVOKE_ALL_FOR_COLD = 4; uint256 private constant LOCK_HOT = 5; uint256 private constant UNLOCK_HOT = 6; uint256 private constant MAKE_SECONDARY_DELEGATION = 7; uint256 private constant MAKE_30_DAY_PRIMARY_DELEGATION = 8; uint256 private constant MAKE_90_DAY_PRIMARY_DELEGATION = 9; // Internal authority model uint256 private constant ALL_DELEGATION = 1; uint256 private constant SUB_DELEGATION = 14; uint256 private constant LEVEL_ONE = 25; uint256 private constant LEVEL_TWO = 24; uint256 private constant LEVEL_THREE = 23; uint96 private constant LEVEL_ONE_KEY = 11000000000000000000000000; uint96 private constant LEVEL_TWO_KEY = 10100000000000000000000000; uint96 private constant LEVEL_THREE_KEY = 10010000000000000000000000; address private constant INITIAL_ADMIN = 0x9F0773aF2b1d3f7cC7030304548A823B4E6b13bB; IEPSDelegationRegister private constant LEGACY_REGISTER = IEPSDelegationRegister(0x88888888888806458312bB6B7Ae0f9a7ad30Ea40); // ====================================================== // STORAGE // ====================================================== // 'Air drop' of EPSAPI to every address uint256 private _epsAPIBalance = type(uint256).max; // Fee to add a live proxy record to the register. If a fee is required this must be sent either: // 1) On the call from the cold to nominate the hot, // 2) If the cold calls through the ERC20 API the record will be in a pending state until // the eth payment has been made from the cold to the register address (note when there is no // fee this step is never required). uint256 private _proxyRegisterFee; // Reward token details: IOAT public rewardToken; uint88 public rewardRate; bool public rewardRateLocked; // Load one item from legacy register? bool public includeLegacy = true; // Decimals uint8 private _decimals = 3; // ENS reverse registrar ENSReverseRegistrar private _ensReverseRegistrar; // EPS treasury address: address private _treasury; // Note that collection delegation 'overrides' global delegation. For example, address A delegates // to address B for all. Address A also delegates to address C for byWassies. When checking // for this delegation for byWassies address B will NOT have the delegation to address A, but address // C WILL. For all collections that are NOT byWassies address B will have the delegation from address A, // and address C will NOT. mapping(bytes32 => uint256) internal _delegationTypesForAddress; // The control integer tells us about the delegation, and is structured as follows: // 98765432129876543211987654321 29 integers per uint96 // ^^^^^-----------------------^ // |||| | 25 Usage types // ||| DelegationClass: 0 = Primary, 1 = Secondary, 2 = Rental (position 26) // || DelegationTimeLimit: Is eternal or time limited. 0 = eternal, 1 = time limited (position 27) // | DelegationScope: Is global, collection or token. 0 = global, 1 = collection, 2 = token (position 28) // Reserved for transaction type on headless protocol calls (position 29) // Note that in token API calls positions 27 and 28 when received hold the provider code // Example 1: this is an entry that delegates primary for all rights for an unlimited time for all // collections: // 00000000000000000000000000001 // Example 2: this is an entry that delegates secondary for all rights for an limited time for all // collections for usages 2, 3, 5 and 24: // 00110100000000000000000010110 // Example 3: this is an entry that delegates rental for all rights for an unlimited time for all // collections: // 00020000000000000000000000001 // Map addresses hashed with tranche to delegation key. The delegation key is the first 20 bytes of a hash // of the delegation data: mapping(bytes32 => EnumerableSet.AddressSet) internal _hotToDelegation; mapping(bytes32 => EnumerableSet.AddressSet) internal _coldToDelegation; mapping(bytes32 => EnumerableSet.AddressSet) internal _tokenToDelegation; // Map a delegation key to delegation record: mapping(address => DelegationRecord) private _delegationRecord; // Map a delegation record to it's metadata (if required). mapping(address => DelegationMetadata) public delegationMetadata; // Hot wallet delegation tranche number mapping(address => uint256) internal _hotWalletTranche; // Cold wallet delegation tranche number mapping(address => uint256) internal _coldWalletTranche; // Map an address to a lock struct mapping(address => LockDetails) private _addressLockDetails; // Map an address to a lock bypass list: mapping(address => EnumerableSet.AddressSet) internal _lockBypassList; // Map cold address to pending payments mapping(address => address[]) public pendingPayments; // ERC20 token relayed fee mapping(address => uint256) private _erc20PerTransactionFee; /** * * * @dev Constructor * * */ constructor() { _addAuthority(SUB_DELEGATION); _addAuthority(LEVEL_ONE); _addAuthority(LEVEL_TWO); _addAuthority(LEVEL_THREE); } // ====================================================== // MODIFIERS // ====================================================== /** * * * @dev onlyLevelOneAdmin - functionality for level one admins * * */ modifier onlyLevelOneAdmin() { if (!isLevelAdmin(_msgSender(), LEVEL_ONE, LEVEL_ONE_KEY)) { revert IncorrectAdminLevel(1); } _; } /** * * * @dev onlyLevelTwoAdmin - functionality for level two admins * * */ modifier onlyLevelTwoAdmin() { if (!isLevelAdmin(_msgSender(), LEVEL_TWO, LEVEL_TWO_KEY)) { revert IncorrectAdminLevel(2); } _; } /** * * * @dev onlyLevelThreeAdmin - functionality for level three admins * * */ modifier onlyLevelThreeAdmin() { if (!isLevelAdmin(_msgSender(), LEVEL_THREE, LEVEL_THREE_KEY)) { revert IncorrectAdminLevel(3); } _; } // ====================================================== // GET DELEGATIONS // ====================================================== /** * * * @dev getDelegationRecord - return the delegation record object for * the provided delegationKey argument * * @param delegationKey_ The address key for this delegation * @return DelegationRecord The delegation record for the passed key * * */ function getDelegationRecord(address delegationKey_) external view returns (DelegationRecord memory) { return (_delegationRecord[delegationKey_]); } /** * * * @dev isValidDelegation - returns whether the arguments passed * result in a valid delegation * * @param hot_ The hot address for the delegation * @param cold_ The cold address for the delegation * @param collection_ The collection for the delegation. Note that address(0) * is passed for global delegations * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return isValid_ Whether this is valid (true) or not (false) * * */ function isValidDelegation( address hot_, address cold_, address collection_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) external view returns (bool isValid_) { (, isValid_) = _getAddresses( hot_, collection_, usageType_, includeSecondary_, includeRental_, cold_ ); return (isValid_); } /** * * * @dev getAddresses - Get all currently valid addresses for a hot address. * - Pass in address(0) to return records that are for ALL collections * - Pass in a collection address to get records for just that collection * - Usage type must be supplied. Only records that match usage type will be returned * @param hot_ The hot address for the delegation * @param collection_ The collection for the delegation. Note that address(0) * is passed for global delegations * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return addresses_ An array of addresses valid for the passed arguments * * */ function getAddresses( address hot_, address collection_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) public view returns (address[] memory addresses_) { (addresses_, ) = _getAddresses( hot_, collection_, usageType_, includeSecondary_, includeRental_, address(0) ); return (addresses_); } /** * * * @dev _getAddresses - Get all currently valid addresses for a hot address. * - Pass in address(0) to return records that are for ALL collections * - Pass in a collection address to get records for just that collection * - Usage type must be supplied. Only records that match usage type will be returned * * @param hot_ The hot address for the delegation * @param collection_ The collection for the delegation. Note that address(0) * is passed for global delegations * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * @param targetCold_ If we are looking for a specifc cold address this will be used * to determine the result of the isValid_ return parameter * * @return addresses_ An array of addresses valid for the passed arguments * @return isValid_ Whether this is valid (true) or not (false) * * */ function _getAddresses( address hot_, address collection_, uint256 usageType_, bool includeSecondary_, bool includeRental_, address targetCold_ ) internal view returns (address[] memory addresses_, bool isValid_) { if ( _includesUsageTypeOrAll( usageType_, _delegationTypesForAddress[ _getDelegationTypeHash(hot_, collection_, false, 0) ] ) || (collection_ != address(0) && _includesUsageTypeOrAll( usageType_, _delegationTypesForAddress[ _getDelegationTypeHash(hot_, address(0), false, 0) ] )) ) { // OK, so the hot_ address has delegated to another address for usage type for this // collection (or globally) for the PRIMARY. This means that // balances associated with the hot_ address will be represented on OTHER addresse(s) for PRIMARY // usage. // As 'rental' is also a primary scoped item we can only proceed if we were including secondary // delegations, and are therefore OK with multiple return results across the register for a // collection / usage type combination: if (!includeSecondary_) { return (new address[](0), false); } } uint256 delegationCount; uint256 addedAddressesCount; ( addresses_, delegationCount, addedAddressesCount, isValid_ ) = _getDelegations( DelegationCheckAddresses(hot_, targetCold_, collection_), usageType_, includeSecondary_, includeRental_ ); if (isValid_) { return (addresses_, isValid_); } if (delegationCount > addedAddressesCount) { assembly { let decrease := sub(delegationCount, addedAddressesCount) mstore(addresses_, sub(mload(addresses_), decrease)) } } if (includeLegacy && addresses_.length == 1) { // One result is the calling hot (no delegations), so check legacy for ONE cold address delegation: address[] memory legacyRecords = LEGACY_REGISTER.getAddresses( hot_, collection_, usageType_, includeSecondary_, includeRental_ ); if (legacyRecords.length > 1) { // See if this cold has an entry on this register, as if it does it has been overriden // and won't be returned from the legacy register: if ( _hasExistingDelegation( legacyRecords[1], address(0), false, 0, usageType_ ) || _hasExistingDelegation( legacyRecords[1], collection_, false, 0, usageType_ ) ) { // We have an overriding delegation on this register, do not include this return (addresses_, false); } if (legacyRecords[1] == targetCold_) { return (addresses_, true); } addresses_ = new address[](2); addresses_[0] = legacyRecords[0]; addresses_[1] = legacyRecords[1]; } } return (addresses_, false); } /** * * * @dev _hasExistingDelegation - return if the passed parameters resolve to an existing * delegaiton on this register * * @param cold_ The cold address for the delegation * @param collection_ The collection for the delegation. Note that address(0) * is passed for global delegations * @param tokenBased_ If this is a token based delegation (true) or not (false) * @param tokenId_ The token ID for token based delegations * @param usageType_ The usage type for the delegation * * @return bool If the passet arguments resolve to an existing delegation (true) ot * not (false) * * */ function _hasExistingDelegation( address cold_, address collection_, bool tokenBased_, uint256 tokenId_, uint256 usageType_ ) internal view returns (bool) { // Get the delegation types for this cold address with the collection scope uint256 currentDelegationTypes = _delegationTypesForAddress[ _getDelegationTypeHash(cold_, collection_, tokenBased_, tokenId_) ]; // Check if this cold address has delegated with collection scope for this usage type: if ( currentDelegationTypes != 0 && ((usageType_ == 1) || _includesUsageTypeOrAll(usageType_, currentDelegationTypes)) ) { // There is an existing delegation return (true); } else { // There is no existing delegation return (false); } } /** * * * @dev _getDelegations - Get delegations for the passed arguments * * @param checkAddresses_ An object holding the hot, cold and collection * addresses for this query * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return addresses_ The valid return addresses for this query * @return delegationCount_ How many delegations were queried * @return addedAddressesCount_ How many addresses were added to the return array * @return isValid_ If we are looking for a specific cold address this will * provide that information. * * * */ function _getDelegations( DelegationCheckAddresses memory checkAddresses_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) internal view returns ( address[] memory addresses_, uint256 delegationCount_, uint256 addedAddressesCount_, bool isValid_ ) { if (checkAddresses_.targetCollection == address(0)) { // We will only be looking for global delegations, collection level delegations will // not be relevant: return _getGlobalDelegations( checkAddresses_, usageType_, includeSecondary_, includeRental_ ); } else { return _getCollectionDelegations( checkAddresses_, usageType_, includeSecondary_, includeRental_ ); } } /** * * * @dev _getGlobalDelegations - Get global delegations for the passed arguments * * @param checkAddresses_ An object holding the hot, cold and collection * addresses for this query * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return addresses_ The valid return addresses for this query * @return possibleCount_ How many delegations were queried * @return actualCount_ How many addresses were added to the return array * @return isValid_ If we are looking for a specific cold address this will * provide that information. * * */ function _getGlobalDelegations( DelegationCheckAddresses memory checkAddresses_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) internal view returns ( address[] memory addresses_, uint256 possibleCount_, uint256 actualCount_, bool isValid_ ) { EnumerableSet.AddressSet storage delegationsToCheck = _hotToDelegation[ _hotMappingKey(checkAddresses_.hot) ]; unchecked { possibleCount_ = delegationsToCheck.length() + 1; addresses_ = new address[](possibleCount_); addresses_[0] = checkAddresses_.hot; actualCount_++; } for (uint256 i = 0; i < (possibleCount_ - 1); i++) { DelegationRecord memory currentDelegation = _delegationRecord[ delegationsToCheck.at(i) ]; if ( // Only proceeed if this ISN'T a collection specific delegation: (_collectionSpecific(currentDelegation.controlInteger)) || ( !_delegationIsValid( DelegationCheckAddresses( checkAddresses_.hot, currentDelegation.cold, address(0) ), DelegationCheckClasses(includeSecondary_, includeRental_, false), currentDelegation.controlInteger, usageType_, 0, ValidityDates( currentDelegation.startDate, currentDelegation.endDate ), delegationsToCheck.at(i) ) ) ) { continue; } if (currentDelegation.cold == checkAddresses_.cold) { return (addresses_, 0, 0, true); } // Made it here. Add it: addresses_[actualCount_] = currentDelegation.cold; unchecked { actualCount_++; } } return (addresses_, possibleCount_, actualCount_, false); } /** * * * @dev _getCollectionDelegations - get collection level delegations for the * passed arguments * * @param checkAddresses_ An object holding the hot, cold and collection * addresses for this query * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return addresses_ The valid return addresses for this query * @return possibleCount_ How many delegations were queried * @return actualCount_ How many addresses were added to the return array * @return isValid_ If we are looking for a specific cold address this will * provide that information. * * */ function _getCollectionDelegations( DelegationCheckAddresses memory checkAddresses_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) internal view returns ( address[] memory addresses_, uint256 possibleCount_, uint256 actualCount_, bool isValid_ ) { EnumerableSet.AddressSet storage delegationsToCheck = _hotToDelegation[ _hotMappingKey(checkAddresses_.hot) ]; unchecked { possibleCount_ = delegationsToCheck.length() + 1; addresses_ = new address[](possibleCount_); addresses_[0] = checkAddresses_.hot; actualCount_++; } // Slightly more complicated, as we have these possibilities: // 1) If the collection on the delegation matches the collection we have been // asked about then this is valid. // 2) If there is a collection on the delegation and it DOESN'T match the // collection we have been asked about then it is invalid. // 3) If there is no collection on the delegation (i.e. it is global) AND // there is no collection level delegation for the cold address it is valid // 4) If there is no collection on the delegation (i.e. it is global) AND // there IS a collection level delegation for the cold address it is INVALID, // as the specific collection delegation 'trumps' the global delegation. for (uint256 i = 0; i < (possibleCount_ - 1); i++) { DelegationRecord memory currentDelegation = _delegationRecord[ delegationsToCheck.at(i) ]; // Is this token specific? If so continue, as we do not return whole // address based delegations for token specific delegations. They can be // access through the beneficiaryOf method if ( _delegationScope(currentDelegation.controlInteger) == DelegationScope.token ) { continue; } address collectionToCheck = address(0); // Is this a collection specific delegation? if (_collectionSpecific(currentDelegation.controlInteger)) { collectionToCheck = checkAddresses_.targetCollection; } else { // Check if the cold address has a collection specific delegation for this collection: // Only proceed if there ISN'T a collection specific delegation for this usage type: if ( _hasCollectionDelegation( currentDelegation.cold, checkAddresses_.targetCollection, usageType_ ) ) { continue; } } if ( !_delegationIsValid( DelegationCheckAddresses( checkAddresses_.hot, currentDelegation.cold, collectionToCheck ), DelegationCheckClasses(includeSecondary_, includeRental_, false), currentDelegation.controlInteger, usageType_, 0, ValidityDates(currentDelegation.startDate, currentDelegation.endDate), delegationsToCheck.at(i) ) ) { continue; } if (currentDelegation.cold == checkAddresses_.cold) { return (addresses_, 0, 0, true); } // Made it here. Add it: addresses_[actualCount_] = currentDelegation.cold; unchecked { actualCount_++; } } return (addresses_, possibleCount_, actualCount_, false); } /** * * * @dev _hasCollectionDelegation - Return if this cold address has a * collection level delegation * * @param cold_ The cold address for the delegation * @param collection_ The collection for the delegation. * @param usageType_ The usage type for the delegation * * @return bool If this has a collection level delegation (true) or not (false) * * */ function _hasCollectionDelegation( address cold_, address collection_, uint256 usageType_ ) internal view returns (bool) { return ( _includesUsageTypeOrAll( usageType_, _delegationTypesForAddress[ _getDelegationTypeHash(cold_, collection_, false, 0) ] ) ); } /** * * * @dev beneficiaryBalanceOf: Returns the beneficiary balance * * @param queryAddress_ The beneficiary address that we are querying * @param contractAddress_ The contract we are checking balances on * @param usageType_ The usage type for the delegation * @param erc1155_ If this is an 1155 contract * @param id_ If we have an 1155 contract to query this has the token Id * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return balance_ The balance for this beneficiary * * */ function beneficiaryBalanceOf( address queryAddress_, address contractAddress_, uint256 usageType_, bool erc1155_, uint256 id_, bool includeSecondary_, bool includeRental_ ) external view returns (uint256 balance_) { address[] memory delegatedAddresses = getAddresses( queryAddress_, contractAddress_, usageType_, includeSecondary_, includeRental_ ); if (!erc1155_) { for (uint256 i = 0; i < delegatedAddresses.length; ) { unchecked { balance_ += ( IERC721(contractAddress_).balanceOf(delegatedAddresses[i]) ); i++; } } } else { for (uint256 i = 0; i < delegatedAddresses.length; ) { unchecked { balance_ += ( IERC1155(contractAddress_).balanceOf(delegatedAddresses[i], id_) ); i++; } } } return (balance_); } /** * * * @dev beneficiaryOf - The beneficiary of for a token, traversing all levels of the * register * * @param collection_ The contract we are checking beneficiaries on * @param tokenId_ The token Id we are querying * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return primaryBeneficiary_ The primary beneficiary - there can be only one * @return secondaryBeneficiaries_ An array of secondary beneficiaries i.e. thos * referenced on non-atomic secondary delegations * * */ function beneficiaryOf( address collection_, uint256 tokenId_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) external view returns ( address primaryBeneficiary_, address[] memory secondaryBeneficiaries_ ) { address owner = IERC721(collection_).ownerOf(tokenId_); ( primaryBeneficiary_, secondaryBeneficiaries_ ) = _getBeneficiaryByTokenDelegation( owner, collection_, tokenId_, usageType_, includeSecondary_, includeRental_ ); // If the benficiary is still the token owner we now want to check if that // owner has a delegation in place for this usageType if (primaryBeneficiary_ == address(0)) { ( primaryBeneficiary_, secondaryBeneficiaries_ ) = _getBeneficiaryByGlobalOrCollectionDelegation( owner, collection_, usageType_, [includeSecondary_, includeRental_] ); } if (primaryBeneficiary_ == address(0)) { primaryBeneficiary_ = owner; } return (primaryBeneficiary_, secondaryBeneficiaries_); } /** * * * @dev _getBeneficiaryByTokenDelegation - get the beneficiary for a token by * valid token delegations * * @param owner_ The owner of the token * @param collection_ The contract we are checking beneficiaries on * @param tokenId_ The token Id we are querying * @param usageType_ The usage type for the delegation * @param includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * @param includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return primaryBeneficiary_ The primary beneficiary - there can be only one * @return secondaryBeneficiaries_ An array of secondary beneficiaries i.e. thos * referenced on non-atomic secondary delegations * * */ function _getBeneficiaryByTokenDelegation( address owner_, address collection_, uint256 tokenId_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) internal view returns ( address primaryBeneficiary_, address[] memory secondaryBeneficiaries_ ) { EnumerableSet.AddressSet storage ownedTokenDelegations = _tokenToDelegation[ _getTokenDelegationHash(owner_, collection_, tokenId_) ]; // We have a local object with an enumerable set of delegation key hashes uint256 tokenDelegationCount = ownedTokenDelegations.length(); uint256 actualCount; secondaryBeneficiaries_ = new address[](tokenDelegationCount); for (uint256 i = 0; i < tokenDelegationCount; i++) { DelegationRecord memory currentDelegation = _delegationRecord[ ownedTokenDelegations.at(i) ]; if ( (!_delegationIsValid( DelegationCheckAddresses(currentDelegation.hot, owner_, collection_), DelegationCheckClasses(includeSecondary_, includeRental_, true), currentDelegation.controlInteger, usageType_, tokenId_, ValidityDates(currentDelegation.startDate, currentDelegation.endDate), ownedTokenDelegations.at(i) ) || (_delegationRecord[ownedTokenDelegations.at(i)].status == DelegationStatus.pending)) ) { continue; } if ( _delegationClass(currentDelegation.controlInteger) != DelegationClass.secondary ) { primaryBeneficiary_ = currentDelegation.hot; } else { // Made it here. Add it: secondaryBeneficiaries_[actualCount] = currentDelegation.hot; unchecked { actualCount++; } } } if (tokenDelegationCount > actualCount) { assembly { let decrease := sub(tokenDelegationCount, actualCount) mstore( secondaryBeneficiaries_, sub(mload(secondaryBeneficiaries_), decrease) ) } } return (primaryBeneficiary_, secondaryBeneficiaries_); } /** * * * @dev _getBeneficiaryByGlobalOrCollectionDelegation - get token Beneficiary by * colleciton or global delegation * * @param owner_ The owner of the token * @param collection_ The contract we are checking beneficiaries on * @param usageType_ The usage type for the delegation * @param inclusionParams_ Placed in an array to reduce local variable count. These are: * [0] includeSecondary_ If this is set to true the register will also check * secondary delegations (i.e. non-atomic delegations) * [1] includeRental_ If this is set to true the register will also check * rental delegations. Note that rental delegations ARE atomic. * * @return primaryBeneficiary_ The primary beneficiary - there can be only one * @return secondaryBeneficiaries_ An array of secondary beneficiaries i.e. thos * referenced on non-atomic secondary delegations * * */ function _getBeneficiaryByGlobalOrCollectionDelegation( address owner_, address collection_, uint256 usageType_, bool[2] memory inclusionParams_ ) internal view returns ( address primaryBeneficiary_, address[] memory secondaryBeneficiaries_ ) { EnumerableSet.AddressSet storage ownerDelegations = _coldToDelegation[ _coldMappingKey(owner_) ]; uint256 actualCount; secondaryBeneficiaries_ = new address[](ownerDelegations.length()); for (uint256 i = 0; i < ownerDelegations.length(); i++) { DelegationRecord memory currentDelegation = _delegationRecord[ ownerDelegations.at(i) ]; address collectionToCheck = address(0); if (_collectionSpecific(currentDelegation.controlInteger)) { collectionToCheck = collection_; } if ( !_delegationIsValid( DelegationCheckAddresses( currentDelegation.hot, owner_, collectionToCheck ), DelegationCheckClasses( inclusionParams_[0], inclusionParams_[1], false ), currentDelegation.controlInteger, usageType_, 0, ValidityDates(currentDelegation.startDate, currentDelegation.endDate), ownerDelegations.at(i) ) || // Check if the cold address has a collection specific delegation for this collection: // Only proceed if there ISN'T a collection specific delegation for this usage type: (!_collectionSpecific(currentDelegation.controlInteger) && ( _includesUsageTypeOrAll( usageType_, _delegationTypesForAddress[ _getDelegationTypeHash(owner_, collection_, false, 0) ] ) )) ) { continue; } if ( _delegationClass(currentDelegation.controlInteger) != DelegationClass.secondary ) { primaryBeneficiary_ = currentDelegation.hot; } else { // Made it here. Add it: secondaryBeneficiaries_[actualCount] = currentDelegation.hot; unchecked { actualCount++; } } } return (primaryBeneficiary_, secondaryBeneficiaries_); } /** * * * @dev delegationFromColdExists - check a cold delegation exists * * @param cold_ The cold address we are querying * @param delegationKey_ The specific address key for a delegation * * @return bool if this exists (true) or not (false) * * */ function delegationFromColdExists(address cold_, address delegationKey_) public view returns (bool) { if (!_coldToDelegation[_coldMappingKey(cold_)].contains(delegationKey_)) { return (false); } return (true); } /** * * * @dev delegationFromHotExists - check a hot delegation exists * * @param hot_ The hot address we are querying * @param delegationKey_ The specific address key for a delegation * * @return bool if this exists (true) or not (false) * * */ function delegationFromHotExists(address hot_, address delegationKey_) public view returns (bool) { if (!_hotToDelegation[_hotMappingKey(hot_)].contains(delegationKey_)) { return (false); } return (true); } /** * * * @dev getAllForHot - Get all delegations at a hot address, formatted nicely * * @param hot_ The hot address we are querying * * @return DelegationReport[] An array of delegation report objects providing * full details of all delegations for this hot address * * */ function getAllForHot(address hot_) external view returns (DelegationReport[] memory) { EnumerableSet.AddressSet storage hotDelegations = _hotToDelegation[ _hotMappingKey(hot_) ]; uint256 delegationCount = hotDelegations.length(); DelegationReport[] memory allForHot = new DelegationReport[]( delegationCount ); for (uint256 i = 0; i < delegationCount; ) { address delegationKey = hotDelegations.at(i); DelegationRecord memory currentDelegation = _delegationRecord[ delegationKey ]; allForHot[i] = _getAllReportLine( hot_, currentDelegation.cold, currentDelegation.controlInteger, delegationFromColdExists(currentDelegation.cold, delegationKey), currentDelegation.startDate, currentDelegation.endDate, delegationKey, currentDelegation.status ); unchecked { i++; } } return (allForHot); } /** * * * @dev getAllForCold - Get all delegations at a cold address, formatted nicely * * @param cold_ The cold address we are querying * * @return DelegationReport[] An array of delegation report objects providing * full details of all delegations for this cold address * * */ function getAllForCold(address cold_) external view returns (DelegationReport[] memory) { EnumerableSet.AddressSet storage coldDelegations = _coldToDelegation[ _coldMappingKey(cold_) ]; uint256 delegationCount = coldDelegations.length(); DelegationReport[] memory allForCold = new DelegationReport[]( delegationCount ); for (uint256 i = 0; i < delegationCount; ) { address delegationKey = coldDelegations.at(i); DelegationRecord memory currentDelegation = _delegationRecord[ delegationKey ]; allForCold[i] = _getAllReportLine( currentDelegation.hot, cold_, currentDelegation.controlInteger, delegationFromHotExists(currentDelegation.hot, delegationKey), currentDelegation.startDate, currentDelegation.endDate, delegationKey, currentDelegation.status ); unchecked { i++; } } return (allForCold); } /** * * * @dev _getAllReportLine - Get a line for the All report * * @param hot_ The hot address we are querying * @param cold_ The cold address we are querying * @param controlInteger_ The control integer for this record * @param bilaterallyValid_ If this entry has a delegation record from the * hot to the cold AND the cold to the hot. This may not be the case, as a result * of revoke all transactions * @param startDate_ The start date of the delegation * @param endDate_ The end date of the delegation * @param delegationKey_ The address key for this delegation * @param status_ The status of this delegation * * @return DelegationReport An object providing full details of this delegation * * */ function _getAllReportLine( address hot_, address cold_, uint96 controlInteger_, bool bilaterallyValid_, uint40 startDate_, uint40 endDate_, address delegationKey_, DelegationStatus status_ ) internal view returns (DelegationReport memory) { DelegationMetadata memory currentMetadata = delegationMetadata[ delegationKey_ ]; return DelegationReport( hot_, cold_, _delegationScope(controlInteger_), _delegationClass(controlInteger_), _delegationTimeLimit(controlInteger_), currentMetadata.collection, currentMetadata.tokenId, startDate_, endDate_, !_hasDates(controlInteger_) || _datesAreValid(startDate_, endDate_), bilaterallyValid_, _delegationScope(controlInteger_) != DelegationScope.token || IERC721(currentMetadata.collection).ownerOf( currentMetadata.tokenId ) == cold_, _decodedUsageTypes(controlInteger_), delegationKey_, controlInteger_, currentMetadata.data, status_ ); } // ====================================================== // MAKE DELEGATIONS // ====================================================== /** * * * @dev makeDelegation - A direct call to setup a new proxy record * * @param hot_ The hot address we are querying * @param cold_ The cold address we are querying * @param targetAddresses_ An array of addresses to make delegations for. These * should be collection addresses, other contract addresses or address(0) for global * @param tokenId_ If this is a token level delegation this should be provided * @param tokenDelegation_ If this is a token delegation (true) or not (false) * @param usageTypes_ An array of usage types for this delegation * @param startDate_ The start date of the delegation * @param endDate_ The end date of the delegation * @param providerCode_ If this delegation has been introduced through a provider this * should hold their unique code * @param delegationClass_ The class of the delegation: 0 = primary, 1 = secondary, * 3 = rental * @param subDelegateKey_ Provide the subdelegate key is performing this delegation from a * valid subdelegate * @param data_ Additional data to include in the delegation e.g. a hyperlink or details * of an IP licensing agreement * * */ function makeDelegation( address hot_, address cold_, address[] memory targetAddresses_, uint256 tokenId_, bool tokenDelegation_, uint8[] memory usageTypes_, uint40 startDate_, uint40 endDate_, uint16 providerCode_, DelegationClass delegationClass_, //0 = primary, 1 = secondary, 2 = rental uint96 subDelegateKey_, bytes memory data_ ) external payable { if (msg.value != _proxyRegisterFee) revert IncorrectProxyRegisterFee(); Delegation memory newDelegation = Delegation( hot_, cold_, targetAddresses_, tokenId_, tokenDelegation_, usageTypes_, startDate_, endDate_, providerCode_, delegationClass_, subDelegateKey_, data_, DelegationStatus.live ); _makeDelegation(newDelegation, _msgSender()); } /** * * * @dev _makeDelegation - perform unified processing for making delegations * * @param newDelegation_ The new delegation object containing all details of the * delegation * @param caller_ The address that has made this call * * */ function _makeDelegation(Delegation memory newDelegation_, address caller_) internal { for (uint256 i = 0; i < newDelegation_.targetAddresses.length; ) { _initialValidation( newDelegation_.hot, newDelegation_.cold, newDelegation_.subDelegateKey, caller_ ); uint96 controlInteger = _constructAndCheckControlInteger( newDelegation_.cold, newDelegation_.targetAddresses[i], newDelegation_.tokenId, newDelegation_.tokenDelegation, newDelegation_.usageTypes, newDelegation_.startDate, newDelegation_.endDate, newDelegation_.delegationClass ); // Create the delegation key: address delegationKey = getDelegationKey( newDelegation_.hot, newDelegation_.cold, newDelegation_.targetAddresses[i], newDelegation_.tokenId, newDelegation_.tokenDelegation, controlInteger, newDelegation_.startDate, newDelegation_.endDate ); if (newDelegation_.tokenDelegation) { // Map the token to the delegation so that it can retrieve and check the details // later. Note that token delegations are mapped in a different way to global // and collection delegations. // Mapping is the cold wallet (current owner), with the contract and token Id _tokenToDelegation[ _getTokenDelegationHash( newDelegation_.cold, newDelegation_.targetAddresses[i], newDelegation_.tokenId ) ].add(delegationKey); } if ( newDelegation_.targetAddresses[i] != address(0) || newDelegation_.data.length != 0 ) { delegationMetadata[delegationKey] = DelegationMetadata( newDelegation_.targetAddresses[i], newDelegation_.tokenId, newDelegation_.data ); } if (newDelegation_.status == DelegationStatus.pending) { pendingPayments[newDelegation_.cold].push(delegationKey); } // Save the delegation for the hot: _hotToDelegation[_hotMappingKey(newDelegation_.hot)].add(delegationKey); // Save the delegation for the cold: _coldToDelegation[_coldMappingKey(newDelegation_.cold)].add( delegationKey ); _delegationRecord[delegationKey] = DelegationRecord( newDelegation_.hot, uint96(controlInteger), newDelegation_.cold, newDelegation_.startDate, newDelegation_.endDate, newDelegation_.status ); _emitDelegationMade(newDelegation_, i); unchecked { i++; } } if (address(rewardToken) != address(0)) { if (newDelegation_.status == DelegationStatus.live) { rewardToken.emitToken( _msgSender(), rewardRate * newDelegation_.targetAddresses.length ); } } } /** * * * @dev _emitDelegationMade - Emit the event for a new delegation * * @param newDelegation_ The new delegation object containing all details of the * delegation * @param index_ The contract / collection address from the addresses array that * has been delegated * * */ function _emitDelegationMade(Delegation memory newDelegation_, uint256 index_) internal { emit DelegationMade( newDelegation_.hot, newDelegation_.cold, newDelegation_.targetAddresses[index_], newDelegation_.tokenId, newDelegation_.tokenDelegation, newDelegation_.usageTypes, newDelegation_.startDate, newDelegation_.endDate, newDelegation_.providerCode, newDelegation_.delegationClass, newDelegation_.subDelegateKey, newDelegation_.data, newDelegation_.status ); } /** * * * @dev _initialValidation - Initial validation of a make delegation call * * @param hot_ The hot address for the delegation * @param cold_ The cold address for the delegation * @param subDelegateKey_ If this is a subdelegate called delegation this will * include the subdelegate key * @param caller_ The caller on this transaction * * */ function _initialValidation( address hot_, address cold_, uint96 subDelegateKey_, address caller_ ) internal view { if (_hotAddressIsLocked(hot_, cold_)) { revert HotAddressIsLockedAndCannotBeDelegatedTo(); } _delegatedAuthorityCheck(caller_, cold_, subDelegateKey_); } /** * * * @dev _getTokenDelegationHash - create a token delegation hash * * @param cold_ The cold address for the delegation * @param collection_ The collection for this delegation hadsh (note is * address(0) for global delegations) * @param tokenId_ The token Id for the hash * * @return bytes32 Hash of the arguments * * */ function _getTokenDelegationHash( address cold_, address collection_, uint256 tokenId_ ) internal view returns (bytes32) { return keccak256( abi.encodePacked( cold_, _coldWalletTranche[cold_], collection_, tokenId_ ) ); } /** * * * @dev _constructAndCheckControlInteger - check for overlapping delegations * and build the control integer for storage * * @param cold_ The cold address for the delegation * @param collection_ The collection for this delegation hadsh (note is * address(0) for global delegations * @param tokenId_ The token Id for this delegation (if relevant) * @param tokenDelegation_ If this is a token delegation (true) or not (false) * @param startDate_ The start date of the delegation * @param endDate_ The end date of the delegation * @param delegationClass_ The class of the delegation: 0 = primary, 1 = secondary, * 3 = rental * * */ function _constructAndCheckControlInteger( address cold_, address collection_, uint256 tokenId_, bool tokenDelegation_, uint8[] memory usageTypes_, uint40 startDate_, uint40 endDate_, DelegationClass delegationClass_ //0 = primary, 1 = secondary, 2 = rental ) internal returns (uint96 controlInteger_) { uint256 usageTypesInteger; unchecked { // Is this global, collection or token based? if (collection_ != address(0)) { if (tokenDelegation_) { // If a cold is delegating a specific token it HAS to own it if (IERC721(collection_).ownerOf(tokenId_) != cold_) { revert CannotDelegatedATokenYouDontOwn(); } controlInteger_ += TOKEN_DELEGATION; } else { controlInteger_ += COLLECTION_DELEGATION; } } // Is this a secondary delegation? if (delegationClass_ == DelegationClass.secondary) { controlInteger_ += SECONDARY_DELEGATION; } // Is this a rental delegation? if (delegationClass_ == DelegationClass.rental) { controlInteger_ += RENTAL_DELEGATION; } // Is this eternal or time based? if (startDate_ + endDate_ != 0) { controlInteger_ += TIME_BASED_DELEGATION; } } // Construct control integers, checking that the cold address hasn't already delegated // these usage codes to another address. for (uint256 i = 0; i < usageTypes_.length; ) { // Check for duplication IF this is a primary delegation: if ( delegationClass_ != DelegationClass.secondary && _hasExistingDelegation( cold_, collection_, tokenDelegation_, tokenId_, usageTypes_[i] ) ) { // Uh oh, we have already delegated this type for this: revert UsageTypeAlreadyDelegated(usageTypes_[i]); } unchecked { if (usageTypes_[i] == 1) { usageTypesInteger += 1; } else { usageTypesInteger += 1 * (10**(usageTypes_[i] - 1)); } i++; } } // All good? OK, record that this delegation is using these usage types by incrementing // the delegation type hash IF this is not a secondary delegation unchecked { if (delegationClass_ != DelegationClass.secondary) { _delegationTypesForAddress[ _getDelegationTypeHash(cold_, collection_, tokenDelegation_, tokenId_) ] += usageTypesInteger; } controlInteger_ += uint96(usageTypesInteger); } return (controlInteger_); } /** * * * @dev _delegationIsValid - Return if a delegation is valid or not * * @param addresses_ The addresses to be checked (hot, cold and collection) * @param classes_ What classes to check (0 = primary, 1 = secondary, 3 = rental) * @param controlInteger_ The conrol integer for this delegation * @param usageType_ The usage type being checked * @param tokenId_ The delegated token Id, if relevant * @param dates_ The start and end date of the delegation * @param receivedDelegationKey_ A received delegation key to check, if provided * * @return valid_ If this is valid (true) or not (false) * * */ function _delegationIsValid( DelegationCheckAddresses memory addresses_, DelegationCheckClasses memory classes_, uint96 controlInteger_, uint256 usageType_, uint256 tokenId_, ValidityDates memory dates_, address receivedDelegationKey_ ) internal view returns (bool valid_) { // If this is a secondary delegation only proceed if we have been // passed that argument if ( (!classes_.secondary && _delegationClass(controlInteger_) == DelegationClass.secondary) || (!classes_.rental && _delegationClass(controlInteger_) == DelegationClass.rental) || !_includesUsageTypeOrAll(usageType_, controlInteger_) ) { return (false); } // Create the delegation key: address delegationKey = getDelegationKey( addresses_.hot, addresses_.cold, addresses_.targetCollection, tokenId_, classes_.token, controlInteger_, dates_.start, dates_.end ); if ( (!delegationFromColdExists(addresses_.cold, delegationKey)) || (!delegationFromHotExists(addresses_.hot, delegationKey)) || (_delegationRecord[delegationKey].status == DelegationStatus.pending) || (_collectionSpecific(controlInteger_) && (delegationMetadata[delegationKey].collection != addresses_.targetCollection)) || (_hasDates(controlInteger_) && !_datesAreValid(dates_.start, dates_.end)) || (receivedDelegationKey_ != address(0) && receivedDelegationKey_ != delegationKey) ) { return (false); } // Made it here. It's valid: return (true); } /** * * * @dev _decodedUsageTypes - decode a control integer into a uint8 array of usage types * * @param controlInteger_ The conrol integer for this delegation * * @return usageTypes_ A uint8 array of usage types * * */ function _decodedUsageTypes(uint256 controlInteger_) internal pure returns (bool[NUMBER_OF_USAGE_TYPES] memory usageTypes_) { for (uint256 i = 0; i < NUMBER_OF_USAGE_TYPES; ) { usageTypes_[i] = _includesUsageType(i + 1, controlInteger_); unchecked { i++; } } return (usageTypes_); } /** * * * @dev _hotMappingKey - Hashes the hot address with the current tranch * * @param hot_ The hot address * * @return bytes32 A hash of the hot with the current tranche for that hot * * */ function _hotMappingKey(address hot_) internal view returns (bytes32) { return (keccak256(abi.encodePacked(hot_, _hotWalletTranche[hot_]))); } /** * * * @dev _coldMappingKey - Hashes the cold address with the current tranch * * @param cold_ The cold address * * @return bytes32 A hash of the cold with the current tranche for that cold * * */ function _coldMappingKey(address cold_) internal view returns (bytes32) { return (keccak256(abi.encodePacked(cold_, _coldWalletTranche[cold_]))); } /** * * * @dev _collectionSpecific - return if delegation is collection specific * * @param controlInteger_ The control integer being queried * * @return bool If this is collection specific (or not) * * */ function _collectionSpecific(uint256 controlInteger_) internal pure returns (bool) { return (_delegationScope(controlInteger_) == DelegationScope.collection); } /** * * * @dev _hasDates - return if delegation is date limited * * @param controlInteger_ The control integer being queried * * @return bool If this delegation has dates (or not) * * */ function _hasDates(uint256 controlInteger_) internal pure returns (bool) { return (_delegationTimeLimit(controlInteger_) == DelegationTimeLimit.limited); } /** * * * @dev _delegationClass - returns the type of delegation (primary, secondary or rental) * * @param controlInteger_ The control integer being queried * * @return DelegationClass The delegation class (primary, secondary, rental) * * */ function _delegationClass(uint256 controlInteger_) internal pure returns (DelegationClass) { if (_controlIntegerValue(26, controlInteger_) == 0) { return (DelegationClass.primary); } if (_controlIntegerValue(26, controlInteger_) == 1) { return (DelegationClass.secondary); } else { return (DelegationClass.rental); } } /** * * * @dev _coldOwnerOrSubDelegate - returns if the passed address is the cold or subdelegate * for the cold * * @param caller_ The calling address * @param cold_ The cold address * @param controlInteger_ The control integer being queried * * @return bool If the caller is a subdelegate for this cold (true), or not (false) * * */ function _coldOwnerOrSubDelegate( address caller_, address cold_, uint96 controlInteger_ ) internal view returns (bool) { if (cold_ == caller_) return (true); return ( _delegationIsValid( DelegationCheckAddresses(caller_, cold_, address(0)), DelegationCheckClasses(true, true, false), controlInteger_, SUB_DELEGATION, 0, ValidityDates(0, 0), address(0) ) ); } /** * * * @dev _delegationTimeLimit - returns the type of time limit (eternal, limited)) * * @param controlInteger_ The control integer being queried * * @return DelegationTimeLimit The delegation time limit (eternal or timelimted) * * */ function _delegationTimeLimit(uint256 controlInteger_) internal pure returns (DelegationTimeLimit) { if (_controlIntegerValue(27, controlInteger_) == 0) { return (DelegationTimeLimit.eternal); } else { return (DelegationTimeLimit.limited); } } /** * * * @dev _delegationScope - returns the scope of the delegation * (0 = global, 1 = collection, 2 = token) * * @param controlInteger_ The control integer being queried * * @return DelegationScope The scope of the delegation (0 = global, * 1 = collection, 2 = token) * * */ function _delegationScope(uint256 controlInteger_) internal pure returns (DelegationScope) { uint256 scope = _controlIntegerValue(28, controlInteger_); if (scope == 0) { return (DelegationScope.global); } if (scope == 1) { return (DelegationScope.collection); } else { return (DelegationScope.token); } } /** * * * @dev _datesAreValid - check if the passed dates are valid * * @param startDate_ The start date of the delegation * @param endDate_ The end date of the delegation * * @return bool If these dates are valid * * */ function _datesAreValid(uint256 startDate_, uint256 endDate_) internal view returns (bool) { return (startDate_ < block.timestamp && endDate_ > block.timestamp); } /** * * * @dev _includesUsageType - check if this includes a given usage type * * @param usageType_ The usage type we are interested in * @param controlInteger_ The control integer being queried * * @return bool If the control integer includes the usage type * * */ function _includesUsageType(uint256 usageType_, uint256 controlInteger_) internal pure returns (bool) { return (_controlIntegerIsTrue(usageType_, controlInteger_)); } /** * * * @dev _includesUsageTypeOrAll - check if this includes a given usage type or is for all * * @param usageType_ The usage type we are interested in * @param controlInteger_ The control integer being queried * * @return bool If the control integer includes the usage type OR all * * */ function _includesUsageTypeOrAll(uint256 usageType_, uint256 controlInteger_) internal pure returns (bool) { // Sub delegation type ALWAYS has to match, it is not included in 'all' if ( usageType_ != SUB_DELEGATION && _controlIntegerIsTrue(ALL_DELEGATION, controlInteger_) ) { return (true); } else { return (_controlIntegerIsTrue(usageType_, controlInteger_)); } } /** * * * @dev getDelegationKey - get the link hash to the delegation metadata * * @param hot_ The hot address we are querying * @param cold_ The cold address we are querying * @param targetAddress_ The collection or contract for the scope of the delegation * @param tokenId_ The token ID for token delegations * @param tokenDelegation_ A bool to indicate this is a token delegation * @param controlInteger_ The control integer for this record * @param startDate_ The start date of the delegation * @param endDate_ The end date of the delegation * * @return address The delegation key * * */ function getDelegationKey( address hot_, address cold_, address targetAddress_, uint256 tokenId_, bool tokenDelegation_, uint96 controlInteger_, uint40 startDate_, uint40 endDate_ ) public pure returns (address) { return ( address( uint160( uint256( keccak256( abi.encodePacked( hot_, cold_, targetAddress_, tokenId_, tokenDelegation_, controlInteger_, startDate_, endDate_ ) ) ) ) ) ); } /** * * * @dev _getDelegationTypeHash - get the hash that points to what delegations * this cold has already made, either for a token, targetAddress (collection), * or for all (using address(0)) * * @param cold_ The cold address we are querying * @param collection_ The collection or contract for the scope of the delegation * @param tokenBased_ A bool to indicate this is a token delegation * @param tokenId_ The token ID for token delegations * * @return bytes32 The delegation type hash * * */ function _getDelegationTypeHash( address cold_, address collection_, bool tokenBased_, uint256 tokenId_ ) internal view returns (bytes32) { return ( keccak256( abi.encodePacked( cold_, collection_, tokenBased_, tokenId_, _coldWalletTranche[cold_] ) ) ); } /** * * @dev _controlIntegerIsTrue - extract a position from the control integer and * confirm if true * * @param position_ The position in the control integer for this item * @param typeInteger_ The type we are looking for * * @return bool If the control integer is set to true * * */ function _controlIntegerIsTrue(uint256 position_, uint256 typeInteger_) internal pure returns (bool) { return (_controlIntegerValue(position_, typeInteger_) == 1); } /** * * * @dev _controlIntegerValue - the value at a position in the control integer * * @param position_ The position in the control integer for this item * @param typeInteger_ The type we are looking for * * @return uint256 The value at the requested position * * */ function _controlIntegerValue(uint256 position_, uint256 typeInteger_) internal pure returns (uint256) { uint256 exponent = (10**(position_)); uint256 divisor; if (position_ == 1) { divisor = 1; } else { divisor = (10**((position_ - 1))); } return ((typeInteger_ % exponent) / divisor); } // ====================================================== // ADDRESS LOCKING // ====================================================== /** * * * @dev getHotAddressLockDetails - get address lock details, both dates * and any bypass addresses * * @param hot_ The hot address being queried * * @return LockDetails The start and end date of any lock * @return address[] A list of bypass addresses * * */ function getHotAddressLockDetails(address hot_) external view returns (LockDetails memory, address[] memory) { return (_addressLockDetails[hot_], _lockBypassList[hot_].values()); } /** * * * @dev unlockAddressUntilTime - Unlock for new delegations from cold * addresses until a predetermined time in the future. E.g. unlock for * 10 minutes while you perform delegations. * * @param lockAtTime_ The time you wish to re-lock for new delegations * * */ function unlockAddressUntilTime(uint40 lockAtTime_) external { _setLockDetails(_msgSender(), lockAtTime_, type(uint40).max); } /** * * * @dev lockAddressUntilDate - Lock address until a future date when it * will unlock * * @param unlockDate_ The time you wish to unlock for new delegations * * */ function lockAddressUntilDate(uint40 unlockDate_) external { _setLockDetails(_msgSender(), uint40(block.timestamp), unlockDate_); } /** * * * @dev lockAddress - Lock address until manually unlocked * * */ function lockAddress() external { _setLockDetails(_msgSender(), uint40(block.timestamp), type(uint40).max); } /** * * * @dev unlockAddress - Unlock address for new delegations from cold addresses * * */ function unlockAddress() external { delete _addressLockDetails[_msgSender()]; } /** * * * @dev addLockBypassAddress - add an entry to the lock bypass list * * @param bypassAddress_ The address to add to your bypass list * * */ function addLockBypassAddress(address bypassAddress_) external { _lockBypassList[_msgSender()].add(bypassAddress_); } /** * * * @dev removeLockBypassAddress - remove an entry from the lock bypass list * * @param bypassAddress_ The address to remove from your bypass list * * */ function removeLockBypassAddress(address bypassAddress_) external { _lockBypassList[_msgSender()].remove(bypassAddress_); } /** * * * @dev _hotAddressIsLocked - returns if this hot address is locked for this cold * * @param hot_ The hot address to be delegated to * @param cold_ The cold address to the delegated from * * @return bool If this hot is locked for calls from this cold * * */ function _hotAddressIsLocked(address hot_, address cold_) internal view returns (bool) { // Get lock details: LockDetails memory lock = _addressLockDetails[hot_]; if (block.timestamp > lock.lockEnd || block.timestamp < lock.lockStart) { // No lock return (false); } // Lock is in force. See if this address is on the bypass list: if (_lockBypassList[hot_].contains(cold_)) { // Cold address is on the bypass list: return (false); } // Made it here? Must be locked: return (true); } /** * * * @dev _setLockDetails - Set the lock details the user has provided * * @param callingAddress_ The calling address to lock * @param lockAt_ The start of the lock * @param unLockAt_ The end of the lock * * */ function _setLockDetails( address callingAddress_, uint40 lockAt_, uint40 unLockAt_ ) internal { _addressLockDetails[callingAddress_] = LockDetails(lockAt_, unLockAt_); } // ====================================================== // REVOKE // ====================================================== /** * * * @dev revokeRecord - Revoking a single record with Key * * @param delegationKey_ The delegation key of the delegation you are * revoking * @param subDelegateKey_ The subdelegate key for this subdelegate if we * are performing a subdelegate action * * */ function revokeRecord(address delegationKey_, uint96 subDelegateKey_) external { _revokeRecord(_msgSender(), delegationKey_, subDelegateKey_); } /** * * * @dev revokeRecordOfGlobalScopeForAllUsages - Revoke a delegation between * two parties for global scope and all usages * * @param participant2_ The second participant on a delegation (can be hot or * cold, the caller must be the other participant) * * */ function revokeRecordOfGlobalScopeForAllUsages(address participant2_) external { _revokeRecordOfGlobalScopeForAllUsages(_msgSender(), participant2_); } /** * * * @dev _revokeRecordOfGlobalScopeForAllUsages: Revoking a global all usages * * @param participant1_ The first participant on a delegation (can be hot or * cold, participant 2 must be the other participant) * @param participant2_ The second participant on a delegation (can be hot or * cold, participant 1 must be the other participant) * * */ function _revokeRecordOfGlobalScopeForAllUsages( address participant1_, address participant2_ ) internal { if (_generateKeyAndRevoke(participant1_, participant2_)) { return; } if (_generateKeyAndRevoke(participant2_, participant1_)) { return; } revert InvalidDelegation(); } /** * * * @dev _generateKeyAndRevoke - Generate a delegation key and perform * a revoke * * @param hot_ The hot address on the delegation * @param cold_ The cold address on the delegation * * */ function _generateKeyAndRevoke(address hot_, address cold_) internal returns (bool) { address delegationKey = getDelegationKey( hot_, cold_, address(0), 0, false, 1, 0, 0 ); DelegationRecord memory currentDelegation = _delegationRecord[ delegationKey ]; if (currentDelegation.hot != address(0)) { _revokeRecord(hot_, delegationKey, 0); return (true); } return (false); } /** * * * @dev _delegatedAuthorityCheck: check for a subdelegate * * @param caller_ The calling address * @param cold_ The cold address on the delegation * @param subDelegateKey_ The subdelegate key * * */ function _delegatedAuthorityCheck( address caller_, address cold_, uint96 subDelegateKey_ ) internal view { if (!_coldOwnerOrSubDelegate(caller_, cold_, subDelegateKey_)) { // This isn't the cold address calling OR a subdelegate passing in their subdelegate key: revert OnlyParticipantOrAuthorisedSubDelegate(); } } /** * * * @dev _revokeRecord - Revoke a delegation record * * @param caller_ The calling address * @param delegationKey_ The key for this delegation * @param subDelegateKey_ The subdelegate key * * */ function _revokeRecord( address caller_, address delegationKey_, uint96 subDelegateKey_ ) internal { // Cache the delegation from cold details: DelegationRecord memory currentDelegation = _delegationRecord[ delegationKey_ ]; if (caller_ != currentDelegation.hot) { _delegatedAuthorityCheck( caller_, currentDelegation.cold, subDelegateKey_ ); } if ( _delegationScope(currentDelegation.controlInteger) == DelegationScope.token ) { DelegationMetadata memory currentMetadata = delegationMetadata[ delegationKey_ ]; bytes32 tokenMappingKey = _getTokenDelegationHash( currentDelegation.cold, currentMetadata.collection, currentMetadata.tokenId ); if (!_tokenToDelegation[tokenMappingKey].contains(delegationKey_)) { revert InvalidDelegation(); } if ( _tokenToDelegation[tokenMappingKey].remove(delegationKey_) && _delegationClass(currentDelegation.controlInteger) != DelegationClass.secondary ) { _decrementUsageTypes( currentDelegation.cold, currentMetadata.collection, true, currentMetadata.tokenId, currentDelegation.controlInteger ); } } // Remove the hot mapping: _hotToDelegation[_hotMappingKey(currentDelegation.hot)].remove( delegationKey_ ); // Adjust the usageTypes record for this cold address IF we removed a record // and this isn't a secondary or token delegation if ( _coldToDelegation[_coldMappingKey(currentDelegation.cold)].remove( delegationKey_ ) && _delegationClass(currentDelegation.controlInteger) != DelegationClass.secondary && _delegationScope(currentDelegation.controlInteger) != DelegationScope.token ) { address collection; if (_collectionSpecific(currentDelegation.controlInteger)) { collection = delegationMetadata[delegationKey_].collection; } _decrementUsageTypes( currentDelegation.cold, collection, false, 0, currentDelegation.controlInteger ); } // Clear the delegation record: delete _delegationRecord[delegationKey_]; // Clear the metadata record: delete delegationMetadata[delegationKey_]; emit DelegationRevoked( currentDelegation.hot, currentDelegation.cold, delegationKey_ ); } /** * * * @dev _decrementUsageTypes - Decrease usage types at this hash * * @param cold_ The ccoldalling address * @param collection_ The collection for this hash (address(0) for global) * @param isTokenDelegation_ Bool to indicate this is a token delegation * @param tokenId_ Token Id if this is a token delegation * @param controlInteger_ The control integer for this delegation * * */ function _decrementUsageTypes( address cold_, address collection_, bool isTokenDelegation_, uint256 tokenId_, uint96 controlInteger_ ) internal { // Create the delegation types hash for this address, collection and token: bytes32 delegationTypeHash = _getDelegationTypeHash( cold_, collection_, isTokenDelegation_, tokenId_ ); _delegationTypesForAddress[delegationTypeHash] -= (controlInteger_ % (10**(LENGTH_OF_CONTROL_INTEGER - NUMBER_OF_USAGE_TYPES))); } /** * * * @dev revokeAllForCold: Cold calls and revokes ALL * * @param cold_ The ccoldalling address * @param subDelegateKey_ The subdelegate key * * */ function revokeAllForCold(address cold_, uint96 subDelegateKey_) external { _delegatedAuthorityCheck(_msgSender(), cold_, subDelegateKey_); // As this clears the entire authority model it is not a suitable option // for this contract's delegations if (cold_ == address(this)) { revert CannotRevokeAllForRegisterAdminHierarchy(); } // This simply updates the cold wallet tranche ID, so all existing // delegations will become invalid _revokeAllForCold(_msgSender()); } /** * * * @dev _revokeAllForCold - Perform the revoke all for a cold address * * @param cold_ The cold address * * */ function _revokeAllForCold(address cold_) internal { // This simply updates the cold wallet tranche ID, so all existing // delegations will become invalid unchecked { _coldWalletTranche[cold_] += 1; } emit AllDelegationsRevokedForCold(cold_); } /** * * * @dev revokeAllForHot: Hot calls and revokes ALL * * */ function revokeAllForHot() external { // This simply updates the hot wallet tranche ID, so all existing // delegations will become invalid _revokeAllForHot(_msgSender()); } /** * * * @dev _revokeAllForHot - Perform the revoke all for a cold address * * @param hot_ The hot address * * */ function _revokeAllForHot(address hot_) internal { // This simply updates the hot wallet tranche ID, so all existing // delegations will become invalid unchecked { _hotWalletTranche[hot_] += 1; } emit AllDelegationsRevokedForHot(hot_); } /** * * * @dev deleteExpired: ANYONE can delete expired records * * @param delegationKey_ The delegation key for the item being removed * * */ function deleteExpired(address delegationKey_) external { DelegationRecord memory currentRecord = _delegationRecord[delegationKey_]; if (currentRecord.hot == address(0)) { revert InvalidDelegation(); } // Only proceed if dates are INVALID: if ( !_hasDates(currentRecord.controlInteger) || _datesAreValid(currentRecord.startDate, currentRecord.endDate) ) { revert CannotDeleteValidDelegation(); } // Remove through a call to revokeRecord: _revokeRecord(currentRecord.hot, delegationKey_, 0); } // ====================================================== // EPSAPI // ====================================================== /** * * * @dev tokenAPICall: receive an EPSAPI call MAKE_PRIMARY_DELEGATION = 1; REVOKE = 2; REVOKE_ALL_FOR_HOT = 3; REVOKE_ALL_FOR_COLD = 4; LOCK_HOT = 5; UNLOCK_HOT = 6; MAKE_SECONDARY_DELEGATION = 7; MAKE_30_DAY_PRIMARY_DELEGATION = 8; MAKE_90_DAY_PRIMARY_DELEGATION = 9; * * @param from_ The "sender" of API token * @param to_ The "receiver" of API token * @param amount_ The amount of API token, which will be broken down * into an address and a uin96 of instruction data * */ // The amount and to address tell us about the delegation, and is structured as follows: // * To address is the counterparty for delegations and revokes, where applicable // * Amount converted as follows: // <address: if present the collection being delegated, otherwise global> <98765432129876543211987654321> 29 integers per uint96 // The integer information maps as follows // 98765432129876543211987654321 // ^-----------------------^|^-^ // | 25 Usage types | | The provider code // | // | The txn code function _tokenAPICall( address from_, address to_, uint256 amount_ ) internal { (address targetAddress, uint96 dataInteger) = _decodeDelegation( bytes32(amount_) ); uint256 actionCode = (dataInteger / 10**3) % 10; if (actionCode == MAKE_PRIMARY_DELEGATION) { _apiDelegation( to_, from_, targetAddress, dataInteger, DelegationClass.primary, 0 ); return; } if (actionCode == REVOKE) { if (targetAddress == address(0)) { // Revoke with global and all usages _revokeRecordOfGlobalScopeForAllUsages(from_, to_); } else { _revokeRecord(from_, targetAddress, 0); } return; } if (actionCode == REVOKE_ALL_FOR_HOT) { _revokeAllForHot(from_); return; } if (actionCode == REVOKE_ALL_FOR_COLD) { _revokeAllForCold(from_); return; } if (actionCode == LOCK_HOT) { _setLockDetails(from_, uint40(block.timestamp), type(uint40).max); return; } if (actionCode == UNLOCK_HOT) { delete _addressLockDetails[from_]; return; } if (actionCode == MAKE_SECONDARY_DELEGATION) { _apiDelegation( to_, from_, targetAddress, dataInteger, DelegationClass.secondary, 0 ); return; } if (actionCode == MAKE_30_DAY_PRIMARY_DELEGATION) { _apiDelegation( to_, from_, targetAddress, dataInteger, DelegationClass.primary, uint40(block.timestamp + 30 * 1 days) ); return; } if (actionCode == MAKE_90_DAY_PRIMARY_DELEGATION) { _apiDelegation( to_, from_, targetAddress, dataInteger, DelegationClass.primary, uint40(block.timestamp + 90 * 1 days) ); return; } revert UnrecognisedEPSAPIAmount(); } /** * * * @dev _apiDelegation - process API introduced delegation * * @param hot_ The hot address * @param cold_ The cold address * @param targetAddress_ The collection from the API payload * @param dataInteger_ The data integer from the API payload * @param class_ The class of this delegation (0 primary, 1 secondary) * @param endDate_ The end date of this delegation * * */ function _apiDelegation( address hot_, address cold_, address targetAddress_, uint256 dataInteger_, DelegationClass class_, uint40 endDate_ ) internal { address[] memory targetAddresses = new address[](1); uint16 providerCode = uint16(dataInteger_ % (10**3)); targetAddresses[0] = (targetAddress_); uint256 usageTypeInteger = ((dataInteger_ % (10**29)) / (10**4)); DelegationStatus status; if (_proxyRegisterFee != 0) { status = DelegationStatus.pending; } uint8[] memory usageTypes; if (usageTypeInteger == 0) { usageTypes = new uint8[](1); usageTypes[0] = uint8(ALL_DELEGATION); } else { uint256 addedCounter; usageTypes = new uint8[](NUMBER_OF_USAGE_TYPES); for (uint256 i = 0; i < NUMBER_OF_USAGE_TYPES; ) { if (_includesUsageType(i + 1, usageTypeInteger)) { usageTypes[addedCounter] = uint8(i + 1); unchecked { addedCounter++; } } unchecked { i++; } } if (NUMBER_OF_USAGE_TYPES > addedCounter) { assembly { let decrease := sub(NUMBER_OF_USAGE_TYPES, addedCounter) mstore(usageTypes, sub(mload(usageTypes), decrease)) } } } _makeDelegation( Delegation( hot_, cold_, targetAddresses, 0, false, usageTypes, 0, endDate_, providerCode, class_, 0, "", status ), cold_ ); } /** * * * @dev _decodeDelegation - decode the delegation data from the bytes32 * * @param data_ Data to decode * * @return address The contract address in the data * @return uint96 The control integer in the data * * */ function _decodeDelegation(bytes32 data_) internal pure returns (address, uint96) { return (address(bytes20(data_)), uint96(uint256(data_))); } /** * * * @dev decimals - Returns the decimals of the token. * * @return uint8 The decimals for the API token * * */ function decimals() external view returns (uint8) { // Decimals set such that all usage types are in the decimal portion return _decimals; } /** * * * @dev name - Returns the name of the token. * * @return string The name of the API token * * */ function name() public pure returns (string memory) { return "EPSAPI"; } /** * * * @dev symbol - Returns the symbol of the token, usually a shorter version of the * name. * * @return string The symbol of the API token * * */ function symbol() public pure returns (string memory) { return "EPSAPI"; } /** * * * @dev balanceOf - Return the user API token balance * * @return uint256 The user balance of API token * * */ function balanceOf(address) public view returns (uint256) { return _epsAPIBalance; } /** * * * @dev totalSupply - See {IERC20-totalSupply}. * * @return uint256 The total supply of API token * * */ function totalSupply() public view returns (uint256) { return _epsAPIBalance; } /** * * * @dev transfer - Doesn't move tokens at all. There was no spoon and there are no tokens. * Rather the quantity being 'sent' denotes the action the user is taking * on the EPS register, and the address they are 'sent' to is the address that is * being referenced by this request. * * @param to The address you are sending tokens to, interpreted by the contract according * to the commands in the amount field * @param amount A combination of the contract address and uint96 control integer. * * @return true * * */ function transfer(address to, uint256 amount) public returns (bool) { _tokenAPICall(msg.sender, to, amount); emit Transfer(msg.sender, to, 0); return (true); } // ====================================================== // RECEIVE ETH // ====================================================== /** * * * @dev receive * * */ receive() external payable { if (msg.value % _proxyRegisterFee == 0) { _payFee(_msgSender(), msg.value); } else { if (!isLevelAdmin(_msgSender(), LEVEL_ONE, LEVEL_ONE_KEY)) revert UnknownAmount(); } } /** * * * @dev _payFee - process receipt of payment * * @param from_ The address the payment is from * @param value_ The value of the payment * * */ function _payFee(address from_, uint256 value_) internal { uint256 pendingPaymentCount = pendingPayments[from_].length; uint256 recordsToBePaid = value_ / _proxyRegisterFee; if (recordsToBePaid > pendingPaymentCount) { revert ToMuchETHForPendingPayments( value_, pendingPaymentCount * _proxyRegisterFee ); } for (uint256 i = pendingPaymentCount; i > 0 && recordsToBePaid > 0; ) { address delegation = pendingPayments[from_][i - 1]; _delegationRecord[delegation].status = DelegationStatus.live; emit DelegationPaid(delegation); pendingPayments[from_].pop(); unchecked { i--; recordsToBePaid--; } } } // ====================================================== // PAYABLE ERC20 INTERFACE // ====================================================== /** * * * @dev onTokenTransfer - call relayed via an ERCOmni payable token type. * * @param sender_ The sender of the payable token type * @param erc20Value_ The value of the tokens sent * @param data_ The data payload, in this case delegation information * */ function onTokenTransfer( address sender_, uint256 erc20Value_, bytes memory data_ ) external payable { // Check valid token relay origin: uint256 erc20Fee = _erc20PerTransactionFee[msg.sender]; if (erc20Fee == 0 || erc20Fee != erc20Value_) { revert InvalidERC20Payment(); } _makeDelegation(_decodeParameters(data_), sender_); } /** * * * @dev _decodeParameters - Decode payable token payload * * @param data_ The data payload, in this case delegation information * * @return Delegation A delegation object * */ function _decodeParameters(bytes memory data_) internal pure returns (Delegation memory) { ( address hot, address cold, address[] memory targetAddresses, uint256 tokenId, bool tokenDelegation, uint8[] memory usageTypes, uint40 startDate, uint40 endDate, uint16 providerCode, DelegationClass class, uint96 subDelegateKey ) = abi.decode( data_, ( address, address, address[], uint256, bool, uint8[], uint40, uint40, uint16, DelegationClass, uint96 ) ); return ( Delegation( hot, cold, targetAddresses, tokenId, tokenDelegation, usageTypes, startDate, endDate, providerCode, class, subDelegateKey, "", DelegationStatus.live ) ); } // ====================================================== // ADMIN FUNCTIONS // ====================================================== /** * * * @dev setRegisterFee - set the fee for accepting a registration * * @param registerFee_ The ETH register fee (if any) * @param erc20_ An ERC20 payable token address * @param erc20Fee_ The fee for the ERC20 type * * */ function setRegisterFees( uint256 registerFee_, address erc20_, uint256 erc20Fee_ ) external onlyLevelTwoAdmin { _proxyRegisterFee = registerFee_; _erc20PerTransactionFee[erc20_] = erc20Fee_; } /** * * * @dev setDecimalsAndBalance - Set decimals and default balance * * @param decimals_ Decimals for the API token * @param balance_ Default balance for the API token * * */ function setDecimalsAndBalance(uint8 decimals_, uint256 balance_) external onlyLevelThreeAdmin { _decimals = decimals_; _epsAPIBalance = balance_; } /** * * * @dev setRewardTokenAndRate - Set the address for the reward token and * the emission rate for this contract * * @param rewardToken_ Reward token address * @param rewardRate_ Emission rate * * */ function setRewardTokenAndRate(address rewardToken_, uint88 rewardRate_) external onlyLevelTwoAdmin { rewardToken = IOAT(rewardToken_); if (!rewardRateLocked) { rewardRate = rewardRate_; } } /** * * * @dev lockRewardRate - Lock the reward rate so it can't be altered * * */ function lockRewardRate() external onlyLevelThreeAdmin { rewardRateLocked = true; } /** * * * @dev setLegacyOff - Turn off the lookup on the legacy contract * * */ function setLegacyOff() external onlyLevelThreeAdmin { includeLegacy = false; } /** * * * @dev setENSName - used to set reverse record so interactions with this contract are easy to * identify * * @param ensName_ Requested ENS name * * */ function setENSName(string memory ensName_) external onlyLevelOneAdmin { _ensReverseRegistrar.setName(ensName_); } /** * * * @dev setENSReverseRegistrar - Set the ENS reverse registrar address * * @param ensReverseRegistrar_ Register contract address * * */ function setENSReverseRegistrar(address ensReverseRegistrar_) external onlyLevelOneAdmin { _ensReverseRegistrar = ENSReverseRegistrar(ensReverseRegistrar_); } /** * * * @dev setTreasuryAddress - set the treasury address * * @param treasuryAddress_ Treasury address * * */ function setTreasuryAddress(address treasuryAddress_) external onlyLevelThreeAdmin { _treasury = treasuryAddress_; } /** * * * @dev withdrawETH - withdraw eth to the treasury: * * @param amount_ Amount to withdraw * * */ function withdrawETH(uint256 amount_) external onlyLevelOneAdmin returns (bool success_) { (success_, ) = _treasury.call{value: amount_}(""); } /** * * * @dev withdrawERC20: Allow any ERC20s to be withdrawn * * @param token_ The token contract * @param amount_ Amount to withdraw * * */ function withdrawERC20(IERC20 token_, uint256 amount_) external onlyLevelOneAdmin { token_.transfer(_treasury, amount_); } /** * * * @dev _addAuthority - Add intial authorities * * @param usage_ The usage type * * */ function _addAuthority(uint256 usage_) internal { uint8[] memory usageTypes = new uint8[](1); usageTypes[0] = uint8(usage_); _makeDelegation( Delegation( INITIAL_ADMIN, address(this), new address[](1), 0, false, usageTypes, 0, 0, 0, DelegationClass.secondary, 0, "", DelegationStatus.live ), address(this) ); } /** * * * @dev isLevelAdmin - Is the passed address a level admin * * @param receivedAddress_ The queried address * @param level_ The level being reviewed * @param key_ The level key required for the lookup * * */ function isLevelAdmin( address receivedAddress_, uint256 level_, uint96 key_ ) public view returns (bool) { return ( _delegationIsValid( DelegationCheckAddresses(receivedAddress_, address(this), address(0)), DelegationCheckClasses(true, true, false), key_, level_, 0, ValidityDates(0, 0), address(0) ) ); } }
// SPDX-License-Identifier: MIT // EPS Contracts v2.0.0 pragma solidity 0.8.17; abstract contract ENSReverseRegistrar { function setName(string memory name) public virtual returns (bytes32); }
// SPDX-License-Identifier: CC0-1.0 // EPS Contracts v2.0.0 // www.eternalproxy.com /** @dev EPS Delegation Register - Interface */ pragma solidity 0.8.17; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "../EPSRewardToken/IOAT.sol"; import "../EPSRewardToken/IERCOmnReceiver.sol"; /** * * @dev Implementation of the EPS proxy register interface. * */ interface IEPSDelegationRegister { // ====================================================== // ENUMS and STRUCTS // ====================================================== // Scope of a delegation: global, collection or token enum DelegationScope { global, collection, token } // Time limit of a delegation: eternal or time limited enum DelegationTimeLimit { eternal, limited } // The Class of a delegation: primary, secondary or rental enum DelegationClass { primary, secondary, rental } // The status of a delegation: enum DelegationStatus { live, pending } // Data output format for a report (used to output both hot and cold // delegation details) struct DelegationReport { address hot; address cold; DelegationScope scope; DelegationClass class; DelegationTimeLimit timeLimit; address collection; uint256 tokenId; uint40 startDate; uint40 endDate; bool validByDate; bool validBilaterally; bool validTokenOwnership; bool[25] usageTypes; address key; uint96 controlInteger; bytes data; DelegationStatus status; } // Delegation record struct DelegationRecord { address hot; uint96 controlInteger; address cold; uint40 startDate; uint40 endDate; DelegationStatus status; } // If a delegation is for a collection, or has additional data, it will need to read the delegation metadata struct DelegationMetadata { address collection; uint256 tokenId; bytes data; } // Details of a hot wallet lock struct LockDetails { uint40 lockStart; uint40 lockEnd; } // Validity dates when checking a delegation struct ValidityDates { uint40 start; uint40 end; } // Delegation struct to hold details of a new delegation struct Delegation { address hot; address cold; address[] targetAddresses; uint256 tokenId; bool tokenDelegation; uint8[] usageTypes; uint40 startDate; uint40 endDate; uint16 providerCode; DelegationClass delegationClass; uint96 subDelegateKey; bytes data; DelegationStatus status; } // Addresses associated with a delegation check struct DelegationCheckAddresses { address hot; address cold; address targetCollection; } // Classes associated with a delegation check struct DelegationCheckClasses { bool secondary; bool rental; bool token; } // Migrated record data struct MigratedRecord { address hot; address cold; } // ====================================================== // CUSTOM ERRORS // ====================================================== error UsageTypeAlreadyDelegated(uint256 usageType); error CannotDeleteValidDelegation(); error CannotDelegatedATokenYouDontOwn(); error IncorrectAdminLevel(uint256 requiredLevel); error OnlyParticipantOrAuthorisedSubDelegate(); error HotAddressIsLockedAndCannotBeDelegatedTo(); error InvalidDelegation(); error ToMuchETHForPendingPayments(uint256 sent, uint256 required); error UnknownAmount(); error InvalidERC20Payment(); error IncorrectProxyRegisterFee(); error UnrecognisedEPSAPIAmount(); error CannotRevokeAllForRegisterAdminHierarchy(); // ====================================================== // EVENTS // ====================================================== event DelegationMade( address indexed hot, address indexed cold, address targetAddress, uint256 tokenId, bool tokenDelegation, uint8[] usageTypes, uint40 startDate, uint40 endDate, uint16 providerCode, DelegationClass delegationClass, uint96 subDelegateKey, bytes data, DelegationStatus status ); event DelegationRevoked(address hot, address cold, address delegationKey); event DelegationPaid(address delegationKey); event AllDelegationsRevokedForHot(address hot); event AllDelegationsRevokedForCold(address cold); event Transfer(address indexed from, address indexed to, uint256 value); /** * * * @dev getDelegationRecord * * */ function getDelegationRecord(address delegationKey_) external view returns (DelegationRecord memory); /** * * * @dev isValidDelegation * * */ function isValidDelegation( address hot_, address cold_, address collection_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) external view returns (bool isValid_); /** * * * @dev getAddresses - Get all currently valid addresses for a hot address. * - Pass in address(0) to return records that are for ALL collections * - Pass in a collection address to get records for just that collection * - Usage type must be supplied. Only records that match usage type will be returned * * */ function getAddresses( address hot_, address collection_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) external view returns (address[] memory addresses_); /** * * * @dev beneficiaryBalanceOf: Returns the beneficiary balance * * */ function beneficiaryBalanceOf( address queryAddress_, address contractAddress_, uint256 usageType_, bool erc1155_, uint256 id_, bool includeSecondary_, bool includeRental_ ) external view returns (uint256 balance_); /** * * * @dev beneficiaryOf * * */ function beneficiaryOf( address collection_, uint256 tokenId_, uint256 usageType_, bool includeSecondary_, bool includeRental_ ) external view returns ( address primaryBeneficiary_, address[] memory secondaryBeneficiaries_ ); /** * * * @dev delegationFromColdExists - check a cold delegation exists * * */ function delegationFromColdExists(address cold_, address delegationKey_) external view returns (bool); /** * * * @dev delegationFromHotExists - check a hot delegation exists * * */ function delegationFromHotExists(address hot_, address delegationKey_) external view returns (bool); /** * * * @dev getAllForHot - Get all delegations at a hot address, formatted nicely * * */ function getAllForHot(address hot_) external view returns (DelegationReport[] memory); /** * * * @dev getAllForCold - Get all delegations at a cold address, formatted nicely * * */ function getAllForCold(address cold_) external view returns (DelegationReport[] memory); /** * * * @dev makeDelegation - A direct call to setup a new proxy record * * */ function makeDelegation( address hot_, address cold_, address[] memory targetAddresses_, uint256 tokenId_, bool tokenDelegation_, uint8[] memory usageTypes_, uint40 startDate_, uint40 endDate_, uint16 providerCode_, DelegationClass delegationClass_, //0 = primary, 1 = secondary, 2 = rental uint96 subDelegateKey_, bytes memory data_ ) external payable; /** * * * @dev getDelegationKey - get the link hash to the delegation metadata * * */ function getDelegationKey( address hot_, address cold_, address targetAddress_, uint256 tokenId_, bool tokenDelegation_, uint96 controlInteger_, uint40 startDate_, uint40 endDate_ ) external pure returns (address); /** * * * @dev getHotAddressLockDetails * * */ function getHotAddressLockDetails(address hot_) external view returns (LockDetails memory, address[] memory); /** * * * @dev lockAddressUntilDate * * */ function lockAddressUntilDate(uint40 unlockDate_) external; /** * * * @dev lockAddress * * */ function lockAddress() external; /** * * * @dev unlockAddress * * */ function unlockAddress() external; /** * * * @dev addLockBypassAddress * * */ function addLockBypassAddress(address bypassAddress_) external; /** * * * @dev removeLockBypassAddress * * */ function removeLockBypassAddress(address bypassAddress_) external; /** * * * @dev revokeRecord: Revoking a single record with Key * * */ function revokeRecord(address delegationKey_, uint96 subDelegateKey_) external; /** * * * @dev revokeGlobalAll * * */ function revokeRecordOfGlobalScopeForAllUsages(address participant2_) external; /** * * * @dev revokeAllForCold: Cold calls and revokes ALL * * */ function revokeAllForCold(address cold_, uint96 subDelegateKey_) external; /** * * * @dev revokeAllForHot: Hot calls and revokes ALL * * */ function revokeAllForHot() external; /** * * * @dev deleteExpired: ANYONE can delete expired records * * */ function deleteExpired(address delegationKey_) external; /** * * * @dev setRegisterFee: set the fee for accepting a registration: * * */ function setRegisterFees( uint256 registerFee_, address erc20_, uint256 erc20Fee_ ) external; /** * * * @dev setRewardTokenAndRate * * */ function setRewardTokenAndRate(address rewardToken_, uint88 rewardRate_) external; /** * * * @dev lockRewardRate * * */ function lockRewardRate() external; /** * * * @dev setLegacyOff * * */ function setLegacyOff() external; /** * * * @dev setENSName (used to set reverse record so interactions with this contract are easy to * identify) * * */ function setENSName(string memory ensName_) external; /** * * * @dev setENSReverseRegistrar * * */ function setENSReverseRegistrar(address ensReverseRegistrar_) external; /** * * * @dev setTreasuryAddress: set the treasury address: * * */ function setTreasuryAddress(address treasuryAddress_) external; /** * * * @dev setDecimalsAndBalance * * */ function setDecimalsAndBalance(uint8 decimals_, uint256 balance_) external; /** * * * @dev withdrawETH: withdraw eth to the treasury: * * */ function withdrawETH(uint256 amount_) external returns (bool success_); /** * * * @dev withdrawERC20: Allow any ERC20s to be withdrawn Note, this is provided to enable the * withdrawal of payments using valid ERC20s. Assets sent here in error are retrieved with * rescueERC20 * * */ function withdrawERC20(IERC20 token_, uint256 amount_) external; /** * * * @dev isLevelAdmin * * */ function isLevelAdmin( address receivedAddress_, uint256 level_, uint96 key_ ) external view returns (bool); }
// 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/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // EPS Contracts v2.0.0 // www.eternalproxy.com /** @dev IERCOmnReceiver - Interface */ pragma solidity 0.8.17; interface IERCOmnReceiver { function onTokenTransfer( address sender, uint256 value, bytes memory data ) external payable; }
// SPDX-License-Identifier: MIT // EPS Contracts v2.0.0 // www.eternalproxy.com /** @dev IOAT - Interface */ pragma solidity 0.8.17; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @dev OAT interface */ interface IOAT is IERC20 { /** * * @dev emitToken * */ function emitToken(address receiver_, uint256 amount_) external; /** * * @dev addEmitter * */ function addEmitter(address emitter_) external; /** * * @dev removeEmitter * */ function removeEmitter(address emitter_) external; /** * * @dev setTreasury * */ function setTreasury(address treasury_) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotDelegatedATokenYouDontOwn","type":"error"},{"inputs":[],"name":"CannotDeleteValidDelegation","type":"error"},{"inputs":[],"name":"CannotRevokeAllForRegisterAdminHierarchy","type":"error"},{"inputs":[],"name":"HotAddressIsLockedAndCannotBeDelegatedTo","type":"error"},{"inputs":[{"internalType":"uint256","name":"requiredLevel","type":"uint256"}],"name":"IncorrectAdminLevel","type":"error"},{"inputs":[],"name":"IncorrectProxyRegisterFee","type":"error"},{"inputs":[],"name":"InvalidDelegation","type":"error"},{"inputs":[],"name":"InvalidERC20Payment","type":"error"},{"inputs":[],"name":"OnlyParticipantOrAuthorisedSubDelegate","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"ToMuchETHForPendingPayments","type":"error"},{"inputs":[],"name":"UnknownAmount","type":"error"},{"inputs":[],"name":"UnrecognisedEPSAPIAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"usageType","type":"uint256"}],"name":"UsageTypeAlreadyDelegated","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"cold","type":"address"}],"name":"AllDelegationsRevokedForCold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"hot","type":"address"}],"name":"AllDelegationsRevokedForHot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"hot","type":"address"},{"indexed":true,"internalType":"address","name":"cold","type":"address"},{"indexed":false,"internalType":"address","name":"targetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"tokenDelegation","type":"bool"},{"indexed":false,"internalType":"uint8[]","name":"usageTypes","type":"uint8[]"},{"indexed":false,"internalType":"uint40","name":"startDate","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"endDate","type":"uint40"},{"indexed":false,"internalType":"uint16","name":"providerCode","type":"uint16"},{"indexed":false,"internalType":"enum IEPSDelegationRegister.DelegationClass","name":"delegationClass","type":"uint8"},{"indexed":false,"internalType":"uint96","name":"subDelegateKey","type":"uint96"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"enum IEPSDelegationRegister.DelegationStatus","name":"status","type":"uint8"}],"name":"DelegationMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"delegationKey","type":"address"}],"name":"DelegationPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"hot","type":"address"},{"indexed":false,"internalType":"address","name":"cold","type":"address"},{"indexed":false,"internalType":"address","name":"delegationKey","type":"address"}],"name":"DelegationRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"bypassAddress_","type":"address"}],"name":"addLockBypassAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"queryAddress_","type":"address"},{"internalType":"address","name":"contractAddress_","type":"address"},{"internalType":"uint256","name":"usageType_","type":"uint256"},{"internalType":"bool","name":"erc1155_","type":"bool"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"bool","name":"includeSecondary_","type":"bool"},{"internalType":"bool","name":"includeRental_","type":"bool"}],"name":"beneficiaryBalanceOf","outputs":[{"internalType":"uint256","name":"balance_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"usageType_","type":"uint256"},{"internalType":"bool","name":"includeSecondary_","type":"bool"},{"internalType":"bool","name":"includeRental_","type":"bool"}],"name":"beneficiaryOf","outputs":[{"internalType":"address","name":"primaryBeneficiary_","type":"address"},{"internalType":"address[]","name":"secondaryBeneficiaries_","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cold_","type":"address"},{"internalType":"address","name":"delegationKey_","type":"address"}],"name":"delegationFromColdExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"},{"internalType":"address","name":"delegationKey_","type":"address"}],"name":"delegationFromHotExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegationMetadata","outputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegationKey_","type":"address"}],"name":"deleteExpired","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"},{"internalType":"address","name":"collection_","type":"address"},{"internalType":"uint256","name":"usageType_","type":"uint256"},{"internalType":"bool","name":"includeSecondary_","type":"bool"},{"internalType":"bool","name":"includeRental_","type":"bool"}],"name":"getAddresses","outputs":[{"internalType":"address[]","name":"addresses_","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cold_","type":"address"}],"name":"getAllForCold","outputs":[{"components":[{"internalType":"address","name":"hot","type":"address"},{"internalType":"address","name":"cold","type":"address"},{"internalType":"enum IEPSDelegationRegister.DelegationScope","name":"scope","type":"uint8"},{"internalType":"enum IEPSDelegationRegister.DelegationClass","name":"class","type":"uint8"},{"internalType":"enum IEPSDelegationRegister.DelegationTimeLimit","name":"timeLimit","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint40","name":"startDate","type":"uint40"},{"internalType":"uint40","name":"endDate","type":"uint40"},{"internalType":"bool","name":"validByDate","type":"bool"},{"internalType":"bool","name":"validBilaterally","type":"bool"},{"internalType":"bool","name":"validTokenOwnership","type":"bool"},{"internalType":"bool[25]","name":"usageTypes","type":"bool[25]"},{"internalType":"address","name":"key","type":"address"},{"internalType":"uint96","name":"controlInteger","type":"uint96"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum IEPSDelegationRegister.DelegationStatus","name":"status","type":"uint8"}],"internalType":"struct IEPSDelegationRegister.DelegationReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"}],"name":"getAllForHot","outputs":[{"components":[{"internalType":"address","name":"hot","type":"address"},{"internalType":"address","name":"cold","type":"address"},{"internalType":"enum IEPSDelegationRegister.DelegationScope","name":"scope","type":"uint8"},{"internalType":"enum IEPSDelegationRegister.DelegationClass","name":"class","type":"uint8"},{"internalType":"enum IEPSDelegationRegister.DelegationTimeLimit","name":"timeLimit","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint40","name":"startDate","type":"uint40"},{"internalType":"uint40","name":"endDate","type":"uint40"},{"internalType":"bool","name":"validByDate","type":"bool"},{"internalType":"bool","name":"validBilaterally","type":"bool"},{"internalType":"bool","name":"validTokenOwnership","type":"bool"},{"internalType":"bool[25]","name":"usageTypes","type":"bool[25]"},{"internalType":"address","name":"key","type":"address"},{"internalType":"uint96","name":"controlInteger","type":"uint96"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum IEPSDelegationRegister.DelegationStatus","name":"status","type":"uint8"}],"internalType":"struct IEPSDelegationRegister.DelegationReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"},{"internalType":"address","name":"cold_","type":"address"},{"internalType":"address","name":"targetAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"bool","name":"tokenDelegation_","type":"bool"},{"internalType":"uint96","name":"controlInteger_","type":"uint96"},{"internalType":"uint40","name":"startDate_","type":"uint40"},{"internalType":"uint40","name":"endDate_","type":"uint40"}],"name":"getDelegationKey","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"delegationKey_","type":"address"}],"name":"getDelegationRecord","outputs":[{"components":[{"internalType":"address","name":"hot","type":"address"},{"internalType":"uint96","name":"controlInteger","type":"uint96"},{"internalType":"address","name":"cold","type":"address"},{"internalType":"uint40","name":"startDate","type":"uint40"},{"internalType":"uint40","name":"endDate","type":"uint40"},{"internalType":"enum IEPSDelegationRegister.DelegationStatus","name":"status","type":"uint8"}],"internalType":"struct IEPSDelegationRegister.DelegationRecord","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"}],"name":"getHotAddressLockDetails","outputs":[{"components":[{"internalType":"uint40","name":"lockStart","type":"uint40"},{"internalType":"uint40","name":"lockEnd","type":"uint40"}],"internalType":"struct IEPSDelegationRegister.LockDetails","name":"","type":"tuple"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"includeLegacy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receivedAddress_","type":"address"},{"internalType":"uint256","name":"level_","type":"uint256"},{"internalType":"uint96","name":"key_","type":"uint96"}],"name":"isLevelAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"},{"internalType":"address","name":"cold_","type":"address"},{"internalType":"address","name":"collection_","type":"address"},{"internalType":"uint256","name":"usageType_","type":"uint256"},{"internalType":"bool","name":"includeSecondary_","type":"bool"},{"internalType":"bool","name":"includeRental_","type":"bool"}],"name":"isValidDelegation","outputs":[{"internalType":"bool","name":"isValid_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"unlockDate_","type":"uint40"}],"name":"lockAddressUntilDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"hot_","type":"address"},{"internalType":"address","name":"cold_","type":"address"},{"internalType":"address[]","name":"targetAddresses_","type":"address[]"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"bool","name":"tokenDelegation_","type":"bool"},{"internalType":"uint8[]","name":"usageTypes_","type":"uint8[]"},{"internalType":"uint40","name":"startDate_","type":"uint40"},{"internalType":"uint40","name":"endDate_","type":"uint40"},{"internalType":"uint16","name":"providerCode_","type":"uint16"},{"internalType":"enum IEPSDelegationRegister.DelegationClass","name":"delegationClass_","type":"uint8"},{"internalType":"uint96","name":"subDelegateKey_","type":"uint96"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"makeDelegation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"sender_","type":"address"},{"internalType":"uint256","name":"erc20Value_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingPayments","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bypassAddress_","type":"address"}],"name":"removeLockBypassAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cold_","type":"address"},{"internalType":"uint96","name":"subDelegateKey_","type":"uint96"}],"name":"revokeAllForCold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeAllForHot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegationKey_","type":"address"},{"internalType":"uint96","name":"subDelegateKey_","type":"uint96"}],"name":"revokeRecord","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"participant2_","type":"address"}],"name":"revokeRecordOfGlobalScopeForAllUsages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint88","name":"","type":"uint88"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRateLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IOAT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"balance_","type":"uint256"}],"name":"setDecimalsAndBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ensName_","type":"string"}],"name":"setENSName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ensReverseRegistrar_","type":"address"}],"name":"setENSReverseRegistrar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setLegacyOff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"registerFee_","type":"uint256"},{"internalType":"address","name":"erc20_","type":"address"},{"internalType":"uint256","name":"erc20Fee_","type":"uint256"}],"name":"setRegisterFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardToken_","type":"address"},{"internalType":"uint88","name":"rewardRate_","type":"uint88"}],"name":"setRewardTokenAndRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasuryAddress_","type":"address"}],"name":"setTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"lockAtTime_","type":"uint40"}],"name":"unlockAddressUntilTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdrawETH","outputs":[{"internalType":"bool","name":"success_","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526000196000556003805461ffff19166103011790553480156200002657600080fd5b5062000033600e6200005d565b6200003f60196200005d565b6200004b60186200005d565b6200005760176200005d565b620017e5565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106200009657620000966200135d565b60ff92909216602092830291909101820152604080516101a081018252739f0773af2b1d3f7cc7030304548a823b4e6b13bb815230818401528151600180825281840184526200014a949293840192828101908036833701905050815260006020820181905260408201819052606082018590526080820181905260a0820181905260c082015260e0016001815260006020808301829052604080519182018152828252830152606090910152306200014e565b5050565b60005b8260400151518110156200058e57825160208401516101408501516200017a929190856200065e565b6000620001d18460200151856040015184815181106200019e576200019e6200135d565b6020026020010151866060015187608001518860a001518960c001518a60e001518b61012001516200069c60201b60201c565b90506000620002258560000151866020015187604001518681518110620001fc57620001fc6200135d565b602002602001015188606001518960800151878b60c001518c60e00151620009d860201b60201c565b90508460800151156200029a576200029881600860006200027689602001518a6040015189815181106200025d576200025d6200135d565b60200260200101518b6060015162000a6960201b60201c565b815260200190815260200160002062000ada60201b62001bb81790919060201c565b505b60006001600160a01b031685604001518481518110620002be57620002be6200135d565b60200260200101516001600160a01b0316141580620002e257506101608501515115155b1562000381576040518060600160405280866040015185815181106200030c576200030c6200135d565b6020908102919091018101516001600160a01b0390811683526060890151838301526101608901516040938401528481166000908152600a8352839020845181546001600160a01b03191692169190911781559083015160018201559082015160028201906200037d908262001409565b5050505b600185610180015160018111156200039d576200039d62001373565b03620003e8576020858101516001600160a01b039081166000908152600f835260408120805460018101825590825292902090910180546001600160a01b0319169183169190911790555b62000406816006600062000276896000015162000afa60201b60201c565b5062000425816007600062000276896020015162000b5460201b60201c565b506040518060c0016040528086600001516001600160a01b03168152602001836001600160601b0316815260200186602001516001600160a01b031681526020018660c0015164ffffffffff1681526020018660e0015164ffffffffff1681526020018661018001516001811115620004a257620004a262001373565b90526001600160a01b03828116600090815260096020908152604091829020845191850151918416600160a01b6001600160601b039093168302178155918401516001808401805460608801516080890151949097166001600160c81b03199091161764ffffffffff9687169094029390931764ffffffffff60c81b198116600160c81b9690931695909502918217835560a0860151939465ffffffffffff60c81b191660ff60f01b199092169190911790600160f01b9084908111156200056e576200056e62001373565b02179055506200058391508690508462000b96565b505060010162000151565b506002546001600160a01b0316156200014a5760008261018001516001811115620005bd57620005bd62001373565b036200014a576002546001600160a01b0316632e6f213633604085015151600254620005fa9190600160a01b90046001600160581b0316620014eb565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156200064157600080fd5b505af115801562000656573d6000803e3d6000fd5b505050505050565b6200066a848462000c50565b156200068957604051630da1844d60e01b815260040160405180910390fd5b6200069681848462000d03565b50505050565b6000806001600160a01b038916156200077857861562000766576040516331a9108f60e11b8152600481018990526001600160a01b03808c1691908b1690636352211e90602401602060405180830381865afa15801562000701573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000727919062001505565b6001600160a01b0316146200074f5760405163400d9f5560e11b815260040160405180910390fd5b6b06765c793fa10079d00000008201915062000778565b6b033b2e3c9fd0803ce8000000820191505b60018360028111156200078f576200078f62001373565b03620007a6576a084595161401484a000000820191505b6002836002811115620007bd57620007bd62001373565b03620007d4576a108b2a2c28029094000000820191505b64ffffffffff8585011615620007f5576a52b7d2dcc80cd2e4000000820191505b60005b86518110156200091257600184600281111562000819576200081962001373565b14158015620008575750620008578b8b8a8c8b86815181106200084057620008406200135d565b602002602001015160ff1662000d3360201b60201c565b15620008a7578681815181106200087257620008726200135d565b6020026020010151604051630aab3ce760e41b81526004016200089e919060ff91909116815260200190565b60405180910390fd5b868181518110620008bc57620008bc6200135d565b602002602001015160ff16600103620008db5760018201915062000909565b6001878281518110620008f257620008f26200135d565b60200260200101510360ff16600a0a600102820191505b600101620007f8565b5060018360028111156200092a576200092a62001373565b14620009cb578060056000620009b38d8d8c8e6001600160a01b0384166000908152600c6020908152604091829020548251606097881b6001600160601b0319908116828501529690971b909516603487015292151560f81b60488601526049850191909152606980850193909352805180850390930183526089909301909252805191012090565b81526020810191909152604001600020805490910190555b0198975050505050505050565b604080516060998a1b6001600160601b0319908116602080840191909152998b1b811660348301529790991b9096166048890152605c88019490945291151560f81b607c87015260a01b6001600160a01b031916607d86015260d890811b6001600160d81b0319908116608987015291901b16608e8401528051607381850301815260939093019052815191012090565b6001600160a01b0383166000908152600c602090815260408083205490516001600160601b0319606088811b82169483019490945260348201929092529185901b166054820152606881018390526088016040516020818303038152906040528051906020012090505b9392505050565b600062000af1836001600160a01b03841662000dea565b90505b92915050565b6001600160a01b0381166000908152600b602090815260408083205490516001600160601b0319606086901b169281019290925260348201526054015b604051602081830303815290604052805190602001209050919050565b6001600160a01b0381166000908152600c602090815260408083205490516001600160601b0319606086901b1692810192909252603482015260540162000b37565b81602001516001600160a01b031682600001516001600160a01b03167f44d84a2c5d27e81636e3182f4601b82564c8086c61dd9a83e3b4586c4db96b2f8460400151848151811062000bec5762000bec6200135d565b6020026020010151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e610180015160405162000c449b9a99989796959493929190620015a2565b60405180910390a35050565b6001600160a01b0382166000908152600d6020908152604080832081518083019092525464ffffffffff808216835265010000000000909104169181018290529042118062000ca65750805164ffffffffff1642105b1562000cb757600091505062000af4565b6001600160a01b0384166000908152600e6020908152604090912062000ce891859062001bcd62000e3c821b17901c565b1562000cf957600091505062000af4565b5060019392505050565b62000d1083838362000e5f565b62000d2e5760405163fed82dc360e01b815260040160405180910390fd5b505050565b6001600160a01b0385166000908152600c602090815260408083205481516001600160601b031960608b811b8216838701528a901b16603482015287151560f81b60488201526049810187905260698082019290925282518082039092018252608901825280519083012083526005909152812054801580159062000dca5750826001148062000dca575062000dca838262000eef565b1562000ddb57600191505062000de1565b60009150505b95945050505050565b600081815260018301602052604081205462000e335750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000af4565b50600062000af4565b6001600160a01b0381166000908152600183016020526040812054151562000af1565b6000836001600160a01b0316836001600160a01b03160362000e845750600162000ad3565b60408051606080820183526001600160a01b0380881683528616602080840191909152600083850181905284519283018552600180845283830152828501819052845180860190955280855290840181905262000ee7938691600e918162000f2e565b949350505050565b6000600e831415801562000f0b575062000f0b6001836200115e565b1562000f1a5750600162000af4565b62000f2683836200115e565b905062000af4565b855160009015801562000f685750600162000f526001600160601b03881662001176565b600281111562000f665762000f6662001373565b145b8062000fa95750866020015115801562000fa95750600262000f936001600160601b03881662001176565b600281111562000fa75762000fa762001373565b145b8062000fc7575062000fc5856001600160601b03881662000eef565b155b1562000fd65750600062001153565b60006200100889600001518a602001518b60400151888c604001518c8a600001518b60200151620009d860201b60201c565b905062001020896020015182620011ba60201b60201c565b1580620010385750885162001036908262001208565b155b806200107e575060016001600160a01b0382166000908152600960205260409020600190810154600160f01b900460ff16908111156200107c576200107c62001373565b145b80620010c85750620010996001600160601b0388166200121d565b8015620010c857506040808a01516001600160a01b038381166000908152600a60205292909220548216911614155b806200110a5750620010e36001600160601b03881662001247565b80156200110a575083516020850151620011089164ffffffffff90811691166200126a565b155b806200113c57506001600160a01b038316158015906200113c5750806001600160a01b0316836001600160a01b031614155b156200114d57600091505062001153565b60019150505b979650505050505050565b60006200116c83836200127f565b6001149392505050565b600062001185601a836200127f565b6000036200119557506000919050565b620011a2601a836200127f565b600103620011b257506001919050565b506002919050565b6000620011f182600783620011cf8762000b54565b815260200190815260200160002062000e3c60201b62001bcd1790919060201c565b620011ff5750600062000af4565b50600192915050565b6000620011f182600683620011cf8762000afa565b600060016200122c83620012db565b600281111562001240576200124062001373565b1492915050565b60006001620012568362001320565b600181111562001240576200124062001373565b6000428310801562000af15750504210919050565b6000806200128f84600a6200177d565b9050600084600103620012a557506001620012c2565b620012b26001866200178b565b620012bf90600a6200177d565b90505b80620012cf8386620017b7565b62000de19190620017ce565b600080620012eb601c846200127f565b905080600003620012ff5750600092915050565b80600103620013115750600192915050565b50600292915050565b50919050565b60006200132f601b836200127f565b6000036200133f57506000919050565b506001919050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b600181811c908216806200139e57607f821691505b6020821081036200131a57634e487b7160e01b600052602260045260246000fd5b601f82111562000d2e57600081815260208120601f850160051c81016020861015620013e85750805b601f850160051c820191505b818110156200065657828155600101620013f4565b81516001600160401b0381111562001425576200142562001347565b6200143d8162001436845462001389565b84620013bf565b602080601f8311600181146200147557600084156200145c5750858301515b600019600386901b1c1916600185901b17855562000656565b600085815260208120601f198616915b82811015620014a65788860151825594840194600190910190840162001485565b5085821015620014c55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141762000af45762000af4620014d5565b6000602082840312156200151857600080fd5b81516001600160a01b038116811462000ad357600080fd5b6003811062001543576200154362001373565b9052565b6000815180845260005b818110156200156f5760208185018101518683018201520162001551565b506000602082860101526020601f19601f83011685010191505092915050565b6002811062001543576200154362001373565b6001600160a01b038c16815260208082018c90528a15156040830152610160606083018190528a519083018190526000916101808401918c82019190845b818110156200160157835160ff1685529382019392820192600101620015e0565b50505064ffffffffff8b1660808501525064ffffffffff891660a084015261ffff881660c08401526200163860e084018862001530565b6001600160601b0386166101008401528281036101208401526200165d818662001547565b915050620016706101408301846200158f565b9c9b505050505050505050505050565b600181815b80851115620016c1578160001904821115620016a557620016a5620014d5565b80851615620016b357918102915b93841c939080029062001685565b509250929050565b600082620016da5750600162000af4565b81620016e95750600062000af4565b81600181146200170257600281146200170d576200172d565b600191505062000af4565b60ff841115620017215762001721620014d5565b50506001821b62000af4565b5060208310610133831016604e8410600b841016171562001752575081810a62000af4565b6200175e838362001680565b8060001904821115620017755762001775620014d5565b029392505050565b600062000af18383620016c9565b8181038181111562000af45762000af4620014d5565b634e487b7160e01b600052601260045260246000fd5b600082620017c957620017c9620017a1565b500690565b600082620017e057620017e0620017a1565b500490565b615f5f80620017f56000396000f3fe60806040526004361061028c5760003560e01c80637be4c1771161015a578063b52d1c19116100c1578063f14210a61161007a578063f14210a614610863578063f228967e14610883578063f50ef9b4146108b0578063f7c618c1146108d0578063fc4a7db1146108f0578063fc662b1c1461091057600080fd5b8063b52d1c19146107a9578063b674d1d7146107c9578063c00206e1146107e3578063c2c97fa314610803578063d800321314610823578063df0003731461084357600080fd5b8063a1db978211610113578063a1db9782146106ef578063a4c0ed361461070f578063a5bc5b8414610722578063a659f29114610737578063a9059cbb14610757578063b30929cd1461077757600080fd5b80637be4c177146106655780637da3f6131461067a5780638546039e1461068f5780638ad2b02d146106af57806395d89b411461034157806397ec8346146106cf57600080fd5b80634a01e225116101fe5780636b33c1ef116101b75780636b33c1ef1461057657806370a082311461059657806371d55afe146105b857806377dd4ac3146105d857806379150d34146105f85780637b0a47ee1461062657600080fd5b80634a01e2251461048e5780634d0800b0146104bc57806354559dbb146104e95780635921920714610516578063652c12eb146105365780636605bfda1461055657600080fd5b806318160ddd1161025057806318160ddd146103b857806327eb8773146103d75780632a468529146103f7578063313ce5671461040c5780634144c028146104365780634815d31c1461045657600080fd5b80630186fce1146102eb5780630294bdab1461032157806306fdde0314610341578063147eb2601461037657806316ab93b11461038957600080fd5b366102e65760015461029e9034614cbf565b6000036102b1576102af3334610930565b005b6102c9335b60196a09195731e2ce35eb000000610aab565b6102af5760405163020ad41b60e11b815260040160405180910390fd5b600080fd5b3480156102f757600080fd5b5060025461030c90600160f81b900460ff1681565b60405190151581526020015b60405180910390f35b34801561032d57600080fd5b506102af61033c366004614cf3565b610b18565b34801561034d57600080fd5b50604080518082018252600681526545505341504960d01b602082015290516103189190614d56565b6102af610384366004614fba565b610b25565b34801561039557600080fd5b506103a96103a4366004614cf3565b610bfd565b604051610318939291906150e4565b3480156103c457600080fd5b506000545b604051908152602001610318565b3480156103e357600080fd5b506103c96103f236600461510b565b610cb2565b34801561040357600080fd5b506102af610e3e565b34801561041857600080fd5b50600354610100900460ff1660405160ff9091168152602001610318565b34801561044257600080fd5b5061030c61045136600461518f565b610aab565b34801561046257600080fd5b506104766104713660046151d1565b610e82565b6040516001600160a01b039091168152602001610318565b34801561049a57600080fd5b506104ae6104a93660046151fd565b610eba565b6040516103189291906152a0565b3480156104c857600080fd5b506104dc6104d7366004614cf3565b610f9d565b604051610318919061532c565b3480156104f557600080fd5b506105096105043660046154bd565b611145565b6040516103189190615507565b34801561052257600080fd5b506102af61053136600461551a565b611163565b34801561054257600080fd5b506102af610551366004614cf3565b6111ac565b34801561056257600080fd5b506102af610571366004614cf3565b6112ee565b34801561058257600080fd5b506102af610591366004615538565b611339565b3480156105a257600080fd5b506103c96105b1366004614cf3565b5060005490565b3480156105c457600080fd5b506102af6105d3366004615570565b611391565b3480156105e457600080fd5b506102af6105f33660046155a9565b61139c565b34801561060457600080fd5b50610618610613366004614cf3565b61143d565b6040516103189291906155f9565b34801561063257600080fd5b5060025461064d90600160a01b90046001600160581b031681565b6040516001600160581b039091168152602001610318565b34801561067157600080fd5b506102af6114ad565b34801561068657600080fd5b506102af6114b8565b34801561069b57600080fd5b5061030c6106aa366004615628565b6114c8565b3480156106bb57600080fd5b506102af6106ca366004615570565b61150d565b3480156106db57600080fd5b5061030c6106ea366004615656565b61154a565b3480156106fb57600080fd5b506102af61070a3660046151d1565b611566565b6102af61071d3660046156cf565b61160d565b34801561072e57600080fd5b506102af611660565b34801561074357600080fd5b506102af610752366004614cf3565b6116a0565b34801561076357600080fd5b5061030c6107723660046151d1565b6116b9565b34801561078357600080fd5b506102af336000908152600d60205260409020805469ffffffffffffffffffff19169055565b3480156107b557600080fd5b506102af6107c4366004614cf3565b611710565b3480156107d557600080fd5b5060035461030c9060ff1681565b3480156107ef57600080fd5b506102af6107fe366004614cf3565b611763565b34801561080f57600080fd5b506102af61081e366004615727565b61177c565b34801561082f57600080fd5b506102af61083e366004615761565b6117fe565b34801561084f57600080fd5b5061030c61085e366004615628565b61180e565b34801561086f57600080fd5b5061030c61087e36600461577e565b611821565b34801561088f57600080fd5b506108a361089e366004614cf3565b6118a7565b6040516103189190615797565b3480156108bc57600080fd5b506104dc6108cb366004614cf3565b61198d565b3480156108dc57600080fd5b50600254610476906001600160a01b031681565b3480156108fc57600080fd5b5061047661090b366004615808565b611b1c565b34801561091c57600080fd5b506102af61092b366004615761565b611bad565b6001600160a01b0382166000908152600f602052604081205460015490919061095990846158be565b90508181111561099957826001548361097291906158d2565b60405163ea626b3f60e01b8152600481019290925260248201526044015b60405180910390fd5b815b6000811180156109ab5750600082115b15610aa4576001600160a01b0385166000908152600f602052604081206109d36001846158e9565b815481106109e3576109e36158fc565b6000918252602080832091909101546001600160a01b031680835260098252604092839020600101805460ff60f01b1916905591518281529192507f851101b6327b058b27638fcf86d96eec48dca48ba23b1f29ed67139449f9407d910160405180910390a16001600160a01b0386166000908152600f60205260409020805480610a7057610a70615912565b600082815260209020810160001990810180546001600160a01b03191690559081019091559283019291909101905061099b565b5050505050565b60408051606080820183526001600160a01b038616825230602080840191909152600083850181905284519283018552600180845283830152828501819052845180860190955280855290840181905292610b0e92919085908790869081611bef565b90505b9392505050565b610b223382611deb565b50565b6001543414610b47576040516333b18e6b60e11b815260040160405180910390fd5b6000604051806101a001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c81526020018b81526020018a151581526020018981526020018864ffffffffff1681526020018764ffffffffff1681526020018661ffff168152602001856002811115610bc357610bc36152c4565b81526001600160601b038516602082015260408101849052606001600090529050610bee8133611e2a565b50505050505050505050505050565b600a602052600090815260409020805460018201546002830180546001600160a01b03909316939192610c2f90615928565b80601f0160208091040260200160405190810160405280929190818152602001828054610c5b90615928565b8015610ca85780601f10610c7d57610100808354040283529160200191610ca8565b820191906000526020600020905b815481529060010190602001808311610c8b57829003601f168201915b5050505050905083565b600080610cc28989898787611145565b905085610d7c5760005b8151811015610d7657886001600160a01b03166370a08231838381518110610cf657610cf66158fc565b60200260200101516040518263ffffffff1660e01b8152600401610d2991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6a919061595c565b90920191600101610ccc565b50610e31565b60005b8151811015610e2f57886001600160a01b031662fdd58e838381518110610da857610da86158fc565b6020026020010151886040518363ffffffff1660e01b8152600401610de29291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015610dff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e23919061595c565b90920191600101610d7f565b505b505b979650505050505050565b610e56335b60176a0847b32ff4cb02fc400000610aab565b610e7657604051630894d7d160e41b815260036004820152602401610990565b6003805460ff19169055565b600f6020528160005260406000208181548110610e9e57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600060606000876001600160a01b0316636352211e886040518263ffffffff1660e01b8152600401610eee91815260200190565b602060405180830381865afa158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f9190615975565b9050610f3f8189898989896122db565b90935091506001600160a01b038316610f8057610f7a81898860405180604001604052808a15151515815260200189151515158152506125c1565b90935091505b6001600160a01b038316610f92578092505b509550959350505050565b6060600060076000610fae8561288e565b815260200190815260200160002090506000610fc9826128e8565b90506000816001600160401b03811115610fe557610fe5614d69565b60405190808252806020026020018201604052801561101e57816020015b61100b614bad565b8152602001906001900390816110035790505b50905060005b8281101561113c57600061103885836128f2565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b860416608084015294955091939092909160a0840191600160f01b900460ff16908111156110d2576110d26152c4565b60018111156110e3576110e36152c4565b90525080516020820151919250611115918a90611100838761180e565b85606001518660800151888860a001516128fe565b848481518110611127576111276158fc565b60209081029190910101525050600101611024565b50949350505050565b606061115686868686866000612c04565b5090505b95945050505050565b61116c33610e43565b61118c57604051630894d7d160e41b815260036004820152602401610990565b6003805460ff9093166101000261ff001990931692909217909155600055565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b8604166080840152929391929160a0840191600160f01b90910460ff1690811115611243576112436152c4565b6001811115611254576112546152c4565b90525080519091506001600160a01b03166112825760405163a9e649e960e01b815260040160405180910390fd5b61129881602001516001600160601b0316612f1a565b15806112bf57506112bf816060015164ffffffffff16826080015164ffffffffff16612f3f565b156112dc576040516287bfad60e21b815260040160405180910390fd5b80516112ea90836000612f53565b5050565b6112f733610e43565b61131757604051630894d7d160e41b815260036004820152602401610990565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b611351335b60186a085ac218dbe29340800000610aab565b61137157604051630894d7d160e41b815260026004820152602401610990565b6001929092556001600160a01b0316600090815260106020526040902055565b6112ea338383612f53565b6113a5336102b6565b6113c557604051630894d7d160e41b815260016004820152602401610990565b60035460405163c47f002760e01b8152620100009091046001600160a01b03169063c47f0027906113fa908490600401614d56565b6020604051808303816000875af1158015611419573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ea919061595c565b604080518082018252600080825260208083018290526001600160a01b0385168252600d8152838220600e909152929020909160609161147c9061339c565b60408051808201909152915464ffffffffff8082168452650100000000009091041660208301529094909350915050565b6114b6336133a9565b565b6114b6334264ffffffffff613400565b60006114f782600760006114db8761288e565b8152602001908152602001600020611bcd90919063ffffffff16565b61150357506000611507565b5060015b92915050565b611518338383613463565b306001600160a01b038316036115415760405163e1bbc9d760e01b815260040160405180910390fd5b6112ea3361348b565b600061155a87868686868b612c04565b98975050505050505050565b61156f336102b6565b61158f57604051630894d7d160e41b815260016004820152602401610990565b6004805460405163a9059cbb60e01b81526001600160a01b03918216928101929092526024820183905283169063a9059cbb906044016020604051808303816000875af11580156115e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611608919061599d565b505050565b3360009081526010602052604090205480158061162a5750828114155b1561164857604051632ab209a560e11b815260040160405180910390fd5b61165a611654836134db565b85611e2a565b50505050565b61166933610e43565b61168957604051630894d7d160e41b815260036004820152602401610990565b600280546001600160f81b0316600160f81b179055565b336000908152600e602052604090206112ea9082611bb8565b60006116c633848461364a565b604051600081526001600160a01b0384169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a350600192915050565b611719336102b6565b61173957604051630894d7d160e41b815260016004820152602401610990565b600380546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b336000908152600e602052604090206112ea90826137c6565b6117853361133e565b6117a557604051630894d7d160e41b815260026004820152602401610990565b600280546001600160a01b0319166001600160a01b0384161790819055600160f81b900460ff166112ea57600280546001600160581b038316600160a01b026affffffffffffffffffffff60a01b199091161790555050565b610b22338264ffffffffff613400565b60006114f782600660006114db876137db565b600061182c336102b6565b61184c57604051630894d7d160e41b815260016004820152602401610990565b6004546040516001600160a01b03909116908390600081818185875af1925050503d8060008114611899576040519150601f19603f3d011682016040523d82523d6000602084013e61189e565b606091505b50909392505050565b6118dd6040805160c08101825260008082526020820181905291810182905260608101829052608081018290529060a082015290565b6001600160a01b03828116600090815260096020908152604091829020825160c08101845281548086168252600160a01b908190046001600160601b0316938201939093526001808301549586169482019490945291840464ffffffffff9081166060840152600160c81b85041660808301529092909160a0840191600160f01b900460ff1690811115611973576119736152c4565b6001811115611984576119846152c4565b90525092915050565b606060006006600061199e856137db565b8152602001908152602001600020905060006119b9826128e8565b90506000816001600160401b038111156119d5576119d5614d69565b604051908082528060200260200182016040528015611a0e57816020015b6119fb614bad565b8152602001906001900390816119f35790505b50905060005b8281101561113c576000611a2885836128f2565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b860416608084015294955091939092909160a0840191600160f01b900460ff1690811115611ac257611ac26152c4565b6001811115611ad357611ad36152c4565b815250509050611af588826040015183602001516111008560400151876114c8565b848481518110611b0757611b076158fc565b60209081029190910101525050600101611a14565b604080516060998a1b6001600160601b0319908116602080840191909152998b1b811660348301529790991b9096166048890152605c88019490945291151560f81b607c87015260a01b6001600160a01b031916607d86015260d890811b6001600160d81b0319908116608987015291901b16608e8401528051607381850301815260939093019052815191012090565b610b22334283613400565b6000610b11836001600160a01b03841661381c565b6001600160a01b03811660009081526001830160205260408120541515610b11565b8551600090158015611c2357506001611c10876001600160601b031661386b565b6002811115611c2157611c216152c4565b145b80611c5d57508660200151158015611c5d57506002611c4a876001600160601b031661386b565b6002811115611c5b57611c5b6152c4565b145b80611c785750611c7685876001600160601b03166138ae565b155b15611c8557506000610e33565b6000611caf89600001518a602001518b60400151888c604001518c8a600001518b60200151611b1c565b9050611cbf8960200151826114c8565b1580611cd457508851611cd2908261180e565b155b80611d16575060016001600160a01b0382166000908152600960205260409020600190810154600160f01b900460ff1690811115611d1457611d146152c4565b145b80611d5c5750611d2e876001600160601b03166138e5565b8015611d5c57506040808a01516001600160a01b038381166000908152600a60205292909220548216911614155b80611d9d5750611d74876001600160601b0316612f1a565b8015611d9d5750611d9b846000015164ffffffffff16856020015164ffffffffff16612f3f565b155b80611dcd57506001600160a01b03831615801590611dcd5750806001600160a01b0316836001600160a01b031614155b15611ddc576000915050610e33565b50600198975050505050505050565b611df58282613903565b15611dfe575050565b611e088183613903565b15611e11575050565b60405163a9e649e960e01b815260040160405180910390fd5b60005b82604001515181101561221457611e5383600001518460200151856101400151856139fd565b6000611e9f846020015185604001518481518110611e7357611e736158fc565b6020026020010151866060015187608001518860a001518960c001518a60e001518b6101200151613a30565b90506000611ee88560000151866020015187604001518681518110611ec657611ec66158fc565b602002602001015188606001518960800151878b60c001518c60e00151611b1c565b9050846080015115611f4a57611f488160086000611f2c89602001518a604001518981518110611f1a57611f1a6158fc565b60200260200101518b60600151613cbf565b8152602001908152602001600020611bb890919063ffffffff16565b505b60006001600160a01b031685604001518481518110611f6b57611f6b6158fc565b60200260200101516001600160a01b0316141580611f8e57506101608501515115155b1561202757604051806060016040528086604001518581518110611fb457611fb46158fc565b6020908102919091018101516001600160a01b0390811683526060890151838301526101608901516040938401528481166000908152600a8352839020845181546001600160a01b03191692169190911781559083015160018201559082015160028201906120239082615a00565b5050505b60018561018001516001811115612040576120406152c4565b0361208a576020858101516001600160a01b039081166000908152600f835260408120805460018101825590825292902090910180546001600160a01b0319169183169190911790555b61209f8160066000611f2c89600001516137db565b506120b58160076000611f2c896020015161288e565b506040518060c0016040528086600001516001600160a01b03168152602001836001600160601b0316815260200186602001516001600160a01b031681526020018660c0015164ffffffffff1681526020018660e0015164ffffffffff168152602001866101800151600181111561212f5761212f6152c4565b90526001600160a01b03828116600090815260096020908152604091829020845191850151918416600160a01b6001600160601b039093168302178155918401516001808401805460608801516080890151949097166001600160c81b03199091161764ffffffffff9687169094029390931764ffffffffff60c81b198116600160c81b9690931695909502918217835560a0860151939465ffffffffffff60c81b191660ff60f01b199092169190911790600160f01b9084908111156121f8576121f86152c4565b021790555090505061220a8584613d29565b5050600101611e2d565b506002546001600160a01b0316156112ea576000826101800151600181111561223f5761223f6152c4565b036112ea576002546001600160a01b0316632e6f2136336040850151516002546122799190600160a01b90046001600160581b03166158d2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156122bf57600080fd5b505af11580156122d3573d6000803e3d6000fd5b505050505050565b600060606000600860006122f08b8b8b613cbf565b81526020019081526020016000209050600061230b826128e8565b90506000816001600160401b0381111561232757612327614d69565b604051908082528060200260200182016040528015612350578160200160208202803683370190505b50935060005b8281101561259f57600060098161236d87856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff1690811115612401576124016152c4565b6001811115612412576124126152c4565b8152505090506124c1604051806060016040528083600001516001600160a01b031681526020018f6001600160a01b031681526020018e6001600160a01b031681525060405180606001604052808c151581526020018b151581526020016001151581525083602001518d8f6040518060400160405280886060015164ffffffffff168152602001886080015164ffffffffff168152506124bc898d6128f290919063ffffffff16565b611bef565b158061251357506001600960006124d888866128f2565b6001600160a01b031681526020810191909152604001600020600190810154600160f01b900460ff1690811115612511576125116152c4565b145b1561251e575061258d565b600161253682602001516001600160601b031661386b565b6002811115612547576125476152c4565b14612555578051965061258b565b806000015186848151811061256c5761256c6158fc565b6001600160a01b03909216602092830291909101909101526001909201915b505b8061259781615abf565b915050612356565b50808211156125b2578351818303900384525b5050505b965096945050505050565b600060606000600760006125d48961288e565b8152602001908152602001600020905060006125ef826128e8565b6001600160401b0381111561260657612606614d69565b60405190808252806020026020018201604052801561262f578160200160208202803683370190505b50925060005b61263e836128e8565b81101561288257600060098161265486856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff16908111156126e8576126e86152c4565b60018111156126f9576126f96152c4565b815250509050600061271782602001516001600160601b03166138e5565b1561271f5750885b604080516060808201835284516001600160a01b0390811683528e811660208085019190915290851683850152835180830185528c51151581528c82015115158183015260008186018190528288015186518088019097529388015164ffffffffff9081168752608089015116928601929092526127a6949092918e916124bc8c8b6128f2565b15806127f457506127c382602001516001600160601b03166138e5565b1580156127f457506127f489600560006127e08f8f600080613dde565b8152602001908152602001600020546138ae565b15612800575050612870565b600161281883602001516001600160601b031661386b565b6002811115612829576128296152c4565b14612837578151965061286d565b816000015186858151811061284e5761284e6158fc565b6001600160a01b03909216602092830291909101909101526001909301925b50505b8061287a81615abf565b915050612635565b50505094509492505050565b6001600160a01b0381166000908152600c602090815260408083205490516001600160601b0319606086901b169281019290925260348201526054015b604051602081830303815290604052805190602001209050919050565b6000611507825490565b6000610b118383613e53565b612906614bad565b6001600160a01b038084166000908152600a602090815260408083208151606081018352815490951685526001810154928501929092526002820180549394939184019161295390615928565b80601f016020809104026020016040519081016040528092919081815260200182805461297f90615928565b80156129cc5780601f106129a1576101008083540402835291602001916129cc565b820191906000526020600020905b8154815290600101906020018083116129af57829003601f168201915b50505050508152505090506040518061022001604052808b6001600160a01b031681526020018a6001600160a01b03168152602001612a138a6001600160601b0316613e7d565b6002811115612a2457612a246152c4565b8152602001612a3b8a6001600160601b031661386b565b6002811115612a4c57612a4c6152c4565b8152602001612a638a6001600160601b0316613ebe565b6001811115612a7457612a746152c4565b815260200182600001516001600160a01b03168152602001826020015181526020018764ffffffffff1681526020018664ffffffffff168152602001612ac28a6001600160601b0316612f1a565b1580612ae15750612ae18864ffffffffff168864ffffffffff16612f3f565b1515815288151560208201526040016002612b048b6001600160601b0316613e7d565b6002811115612b1557612b156152c4565b141580612b9c5750825160208401516040516331a9108f60e11b815260048101919091526001600160a01b038d8116921690636352211e90602401602060405180830381865afa158015612b6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b919190615975565b6001600160a01b0316145b15158152602001612bb58a6001600160601b0316613ee2565b8152602001856001600160a01b03168152602001896001600160601b0316815260200182604001518152602001846001811115612bf457612bf46152c4565b90529a9950505050505050505050565b60606000612c1d86600560006127e08c8c600080613dde565b80612c4c57506001600160a01b03871615801590612c4c5750612c4c86600560006127e08c6000806000613dde565b15612c6e5784612c6e57505060408051600080825260208201909252906125b6565b600080612cb260405180606001604052808c6001600160a01b03168152602001876001600160a01b031681526020018b6001600160a01b0316815250898989613f2e565b929650919450925090508215612cc95750506125b6565b80821115612cdb578351818303900384525b60035460ff168015612cee575083516001145b15612f09576040516354559dbb60e01b81526001600160a01b03808c1660048301528a16602482015260448101899052871515606482015286151560848201526000907388888888888806458312bb6b7ae0f9a7ad30ea40906354559dbb9060a401600060405180830381865afa158015612d6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d959190810190615b3c565b9050600181511115612f0757612dca81600181518110612db757612db76158fc565b602002602001015160008060008d613f82565b80612df85750612df881600181518110612de657612de66158fc565b60200260200101518b6000808d613f82565b15612e0a5750600092506125b6915050565b856001600160a01b031681600181518110612e2757612e276158fc565b60200260200101516001600160a01b031603612e4a5750600192506125b6915050565b604080516002808252606082018352909160208301908036833701905050945080600081518110612e7d57612e7d6158fc565b602002602001015185600081518110612e9857612e986158fc565b60200260200101906001600160a01b031690816001600160a01b03168152505080600181518110612ecb57612ecb6158fc565b602002602001015185600181518110612ee657612ee66158fc565b60200260200101906001600160a01b031690816001600160a01b0316815250505b505b506000915050965096945050505050565b60006001612f2783613ebe565b6001811115612f3857612f386152c4565b1492915050565b60004283108015610b115750504210919050565b6001600160a01b038281166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b8604166080840152929391929160a0840191600160f01b90910460ff1690811115612fea57612fea6152c4565b6001811115612ffb57612ffb6152c4565b90525080519091506001600160a01b038581169116146130245761302484826040015184613463565b600261303c82602001516001600160601b0316613e7d565b600281111561304d5761304d6152c4565b036131e5576001600160a01b038084166000908152600a602090815260408083208151606081018352815490951685526001810154928501929092526002820180549394939184019161309f90615928565b80601f01602080910402602001604051908101604052809291908181526020018280546130cb90615928565b80156131185780601f106130ed57610100808354040283529160200191613118565b820191906000526020600020905b8154815290600101906020018083116130fb57829003601f168201915b5050505050815250509050600061313c836040015183600001518460200151613cbf565b60008181526008602052604090209091506131579086611bcd565b6131745760405163a9e649e960e01b815260040160405180910390fd5b600081815260086020526040902061318c90866137c6565b80156131bf575060016131ab84602001516001600160601b031661386b565b60028111156131bc576131bc6152c4565b14155b156131e2576131e283604001518360000151600185602001518760200151613fdf565b50505b61321683600660006131fa85600001516137db565b81526020019081526020016000206137c690919063ffffffff16565b5061322c83600760006131fa856040015161288e565b801561325f5750600161324b82602001516001600160601b031661386b565b600281111561325c5761325c6152c4565b14155b80156132925750600261327e82602001516001600160601b0316613e7d565b600281111561328f5761328f6152c4565b14155b156132e95760006132af82602001516001600160601b03166138e5565b156132d157506001600160a01b038084166000908152600a6020526040902054165b6132e78260400151826000808660200151613fdf565b505b6001600160a01b0383166000908152600960209081526040808320838155600190810180546001600160f81b0319169055600a909252822080546001600160a01b0319168155908101829055906133436002830182614c37565b5050805160408083015181516001600160a01b039384168152908316602082015291851682820152517f59ae3c34e9447e6c9676b72ba973ce1e412d1051a6da544ac93e2a07ef04259b9181900360600190a150505050565b60606000610b1183614044565b6001600160a01b0381166000818152600b60209081526040918290208054600101905590519182527f17847ea98d58f1bba43d4d7add9ace4b715eb6374a39c43445d322b747d6001991015b60405180910390a150565b60408051808201825264ffffffffff938416815291831660208084019182526001600160a01b039095166000908152600d90955293209051815493518316650100000000000269ffffffffffffffffffff19909416921691909117919091179055565b61346e8383836140a0565b6116085760405163fed82dc360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600c60209081526040918290208054600101905590519182527f150d16c5ed87101ded5915d2c85572217aa147e5f50f384305123e8c6c5680da91016133f5565b604080516101a08101825260008082526020820181905260609282018390528282018190526080820181905260a0820183905260c0820181905260e0820181905261010082018190526101208201819052610140820181905261016082019290925261018081019190915260008060008060008060008060008060008c80602001905181019061356b9190615c0b565b9a509a509a509a509a509a509a509a509a509a509a50604051806101a001604052808c6001600160a01b031681526020018b6001600160a01b031681526020018a815260200189815260200188151581526020018781526020018664ffffffffff1681526020018564ffffffffff1681526020018461ffff1681526020018360028111156135fb576135fb6152c4565b8152602001826001600160601b0316815260200160405180602001604052806000815250815260200160006001811115613637576136376152c4565b90529d9c50505050505050505050505050565b606081901c816000600a6136606103e884615d04565b61366a9190615d2a565b6001600160601b0316905060018103613695576122d3858785856001600160601b0316600080614124565b600281036136c6576001600160a01b0383166136ba576136b58686611deb565b6122d3565b6122d386846000612f53565b600381036136d7576122d3866133a9565b600481036136e8576122d38661348b565b60058103613700576122d3864264ffffffffff613400565b60068103613739575050506001600160a01b039092166000908152600d60205260409020805469ffffffffffffffffffff191690555050565b6007810361375a576122d3858785856001600160601b031660016000614124565b60088103613786576122d38587856001600160601b03861660006137814262278d00615d50565b614124565b600981036137ad576122d38587856001600160601b0386166000613781426276a700615d50565b604051631ec9ca4160e21b815260040160405180910390fd5b6000610b11836001600160a01b038416614382565b6001600160a01b0381166000908152600b602090815260408083205490516001600160601b0319606086901b169281019290925260348201526054016128cb565b600081815260018301602052604081205461386357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611507565b506000611507565b6000613878601a83614475565b60000361388757506000919050565b613892601a83614475565b6001036138a157506001919050565b506002919050565b919050565b6000600e83141580156138c757506138c76001836144c5565b156138d457506001611507565b6138de83836144c5565b9050611507565b600060016138f283613e7d565b6002811115612f3857612f386152c4565b60008061391a848460008060006001600080611b1c565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b860416608084015294955091939092909160a0840191600160f01b900460ff16908111156139b4576139b46152c4565b60018111156139c5576139c56152c4565b90525080519091506001600160a01b0316156139f2576139e785836000612f53565b600192505050611507565b506000949350505050565b613a0784846144db565b15613a2557604051630da1844d60e01b815260040160405180910390fd5b61165a818484613463565b6000806001600160a01b03891615613b05578615613af3576040516331a9108f60e11b8152600481018990526001600160a01b03808c1691908b1690636352211e90602401602060405180830381865afa158015613a92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab69190615975565b6001600160a01b031614613add5760405163400d9f5560e11b815260040160405180910390fd5b6b06765c793fa10079d000000082019150613b05565b6b033b2e3c9fd0803ce8000000820191505b6001836002811115613b1957613b196152c4565b03613b2f576a084595161401484a000000820191505b6002836002811115613b4357613b436152c4565b03613b59576a108b2a2c28029094000000820191505b64ffffffffff8585011615613b79576a52b7d2dcc80cd2e4000000820191505b60005b8651811015613c6f576001846002811115613b9957613b996152c4565b14158015613bcb5750613bcb8b8b8a8c8b8681518110613bbb57613bbb6158fc565b602002602001015160ff16613f82565b15613c0d57868181518110613be257613be26158fc565b6020026020010151604051630aab3ce760e41b8152600401610990919060ff91909116815260200190565b868181518110613c1f57613c1f6158fc565b602002602001015160ff16600103613c3c57600182019150613c67565b6001878281518110613c5057613c506158fc565b60200260200101510360ff16600a0a600102820191505b600101613b7c565b506001836002811115613c8457613c846152c4565b14613cb2578060056000613c9a8d8d8c8e613dde565b81526020810191909152604001600020805490910190555b0198975050505050505050565b6001600160a01b0383166000908152600c60209081526040918290205482516001600160601b0319606097881b81168285015260348201929092529490951b9094166054840152606880840192909252805180840390920182526088909201909152805191012090565b81602001516001600160a01b031682600001516001600160a01b03167f44d84a2c5d27e81636e3182f4601b82564c8086c61dd9a83e3b4586c4db96b2f84604001518481518110613d7c57613d7c6158fc565b6020026020010151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e6101800151604051613dd29b9a99989796959493929190615d63565b60405180910390a35050565b6001600160a01b0384166000908152600c60209081526040918290205482516001600160601b0319606098891b8116828501529690971b909516603487015292151560f81b60488601526049850191909152606980850193909352805180850390930183526089909301909252805191012090565b6000826000018281548110613e6a57613e6a6158fc565b9060005260206000200154905092915050565b600080613e8b601c84614475565b905080600003613e9e5750600092915050565b80600103613eaf5750600192915050565b50600292915050565b50919050565b6000613ecb601b83614475565b600003613eda57506000919050565b506001919050565b613eea614c71565b60005b6019811015613eb857613f0a613f04826001615d50565b8461457a565b828260198110613f1c57613f1c6158fc565b91151560209092020152600101613eed565b60606000806000806001600160a01b031688604001516001600160a01b031603613f6b57613f5e88888888614586565b9350935093509350613f77565b613f5e88888888614868565b945094509450949050565b60008060056000613f9589898989613dde565b815260200190815260200160002054905080600014158015613fc657508260011480613fc65750613fc683826138ae565b15613fd557600191505061115a565b600091505061115a565b6000613fed86868686613dde565b9050613ffb6019601d6158e9565b61400690600a615f1d565b614019906001600160601b038416614cbf565b600082815260056020526040812080549091906140379084906158e9565b9091555050505050505050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561409457602002820191906000526020600020905b815481526020019060010190808311614080575b50505050509050919050565b6000836001600160a01b0316836001600160a01b0316036140c357506001610b11565b60408051606080820183526001600160a01b03808816835286166020808401919091526000838501819052845192830185526001808452838301528285018190528451808601909552808552908401819052610b0e938691600e9181611bef565b6040805160018082528183019092526000916020808301908036833701905050905060006141546103e886614cbf565b9050858260008151811061416a5761416a6158fc565b6001600160a01b0390921660209283029190910190910152600061271061419e6c01431e0fae6d7217caa000000088614cbf565b6141a891906158be565b905060006001546000146141ba575060015b6060826000036142125760408051600180825281830190925290602080830190803683370190505090506001816000815181106141f9576141f96158fc565b602002602001019060ff16908160ff16815250506142b1565b6040805160198082526103408201909252600091602082016103208036833701905050915060005b601981101561429a57614257614251826001615d50565b8661457a565b1561429257614267816001615d50565b838381518110614279576142796158fc565b60ff909216602092830291909101909101526001909101905b60010161423a565b5080601911156142af57815181016018190182525b505b614375604051806101a001604052808d6001600160a01b031681526020018c6001600160a01b0316815260200187815260200160008152602001600015158152602001838152602001600064ffffffffff1681526020018864ffffffffff1681526020018661ffff168152602001896002811115614331576143316152c4565b815260200160006001600160601b0316815260200160405180602001604052806000815250815260200184600181111561436d5761436d6152c4565b90528b611e2a565b5050505050505050505050565b6000818152600183016020526040812054801561446b5760006143a66001836158e9565b85549091506000906143ba906001906158e9565b905081811461441f5760008660000182815481106143da576143da6158fc565b90600052602060002001549050808760000184815481106143fd576143fd6158fc565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061443057614430615912565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611507565b6000915050611507565b60008061448384600a615f1d565b9050600084600103614497575060016144b0565b6144a26001866158e9565b6144ad90600a615f1d565b90505b806144bb8386614cbf565b61115a91906158be565b60006144d18383614475565b6001149392505050565b6001600160a01b0382166000908152600d6020908152604080832081518083019092525464ffffffffff80821683526501000000000090910416918101829052904211806145305750805164ffffffffff1642105b1561453f576000915050611507565b6001600160a01b0384166000908152600e602052604090206145619084611bcd565b15614570576000915050611507565b5060019392505050565b6000610b1183836144c5565b60606000806000806006600061459f8b600001516137db565b815260200190815260200160002090506145b8816128e8565b6001019350836001600160401b038111156145d5576145d5614d69565b6040519080825280602002602001820160405280156145fe578160200160208202803683370190505b509450886000015185600081518110614619576146196158fc565b6001600160a01b039092166020928302919091019091015260019092019160005b6146456001866158e9565b81101561485757600060098161465b85856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff16908111156146ef576146ef6152c4565b6001811115614700576147006152c4565b81525050905061471c81602001516001600160601b03166138e5565b806147ce57506147cc60405180606001604052808d600001516001600160a01b0316815260200183604001516001600160a01b0316815260200160006001600160a01b031681525060405180606001604052808c151581526020018b151581526020016000151581525083602001518d60006040518060400160405280886060015164ffffffffff168152602001886080015164ffffffffff168152506124bc898b6128f290919063ffffffff16565b155b156147d95750614845565b8a602001516001600160a01b031681604001516001600160a01b03160361480e57506000945084935060019250613f77915050565b8060400151878681518110614825576148256158fc565b6001600160a01b0390921660209283029190910190910152506001909301925b8061484f81615abf565b91505061463a565b506000915050945094509450949050565b6060600080600080600660006148818b600001516137db565b8152602001908152602001600020905061489a816128e8565b6001019350836001600160401b038111156148b7576148b7614d69565b6040519080825280602002602001820160405280156148e0578160200160208202803683370190505b5094508860000151856000815181106148fb576148fb6158fc565b6001600160a01b039092166020928302919091019091015260019092019160005b6149276001866158e9565b81101561485757600060098161493d85856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff16908111156149d1576149d16152c4565b60018111156149e2576149e26152c4565b905250905060026149ff82602001516001600160601b0316613e7d565b6002811115614a1057614a106152c4565b03614a1b5750614b84565b6000614a3382602001516001600160601b03166138e5565b15614a43575060408b0151614a62565b614a5682604001518d604001518d614b96565b15614a62575050614b84565b614b0b60405180606001604052808e600001516001600160a01b0316815260200184604001516001600160a01b03168152602001836001600160a01b031681525060405180606001604052808d151581526020018c151581526020016000151581525084602001518e60006040518060400160405280896060015164ffffffffff168152602001896080015164ffffffffff168152506124bc8a8c6128f290919063ffffffff16565b614b16575050614b84565b8b602001516001600160a01b031682604001516001600160a01b031603614b4c57506000955085945060019350613f7792505050565b8160400151888781518110614b6357614b636158fc565b6001600160a01b039092166020928302919091019091015250506001909301925b80614b8e81615abf565b91505061491c565b6000610b0e82600560006127e08888600080613dde565b604080516102208101825260008082526020820181905290918201908152602001600081526020016000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e082015261010001614c16614c71565b81526000602082018190526040820181905260608083015260809091015290565b508054614c4390615928565b6000825580601f10614c53575050565b601f016020900490600052602060002090810190610b229190614c90565b6040518061032001604052806019906020820280368337509192915050565b5b80821115614ca55760008155600101614c91565b5090565b634e487b7160e01b600052601260045260246000fd5b600082614cce57614cce614ca9565b500690565b6001600160a01b0381168114610b2257600080fd5b80356138a981614cd3565b600060208284031215614d0557600080fd5b8135610b1181614cd3565b6000815180845260005b81811015614d3657602081850181015186830182015201614d1a565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b116020830184614d10565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614da757614da7614d69565b604052919050565b60006001600160401b03821115614dc857614dc8614d69565b5060051b60200190565b600082601f830112614de357600080fd5b81356020614df8614df383614daf565b614d7f565b82815260059290921b84018101918181019086841115614e1757600080fd5b8286015b84811015614e3b578035614e2e81614cd3565b8352918301918301614e1b565b509695505050505050565b8015158114610b2257600080fd5b80356138a981614e46565b60ff81168114610b2257600080fd5b600082601f830112614e7f57600080fd5b81356020614e8f614df383614daf565b82815260059290921b84018101918181019086841115614eae57600080fd5b8286015b84811015614e3b578035614ec581614e5f565b8352918301918301614eb2565b64ffffffffff81168114610b2257600080fd5b80356138a981614ed2565b61ffff81168114610b2257600080fd5b80356138a981614ef0565b60038110610b2257600080fd5b80356138a981614f0b565b6001600160601b0381168114610b2257600080fd5b80356138a981614f23565b60006001600160401b03831115614f5c57614f5c614d69565b614f6f601f8401601f1916602001614d7f565b9050828152838383011115614f8357600080fd5b828260208301376000602084830101529392505050565b600082601f830112614fab57600080fd5b610b1183833560208501614f43565b6000806000806000806000806000806000806101808d8f031215614fdd57600080fd5b614fe68d614ce8565b9b50614ff460208e01614ce8565b9a506001600160401b0360408e0135111561500e57600080fd5b61501e8e60408f01358f01614dd2565b995060608d0135985061503360808e01614e54565b97506001600160401b0360a08e0135111561504d57600080fd5b61505d8e60a08f01358f01614e6e565b965061506b60c08e01614ee5565b955061507960e08e01614ee5565b94506150886101008e01614f00565b93506150976101208e01614f18565b92506150a66101408e01614f38565b91506001600160401b036101608e013511156150c157600080fd5b6150d28e6101608f01358f01614f9a565b90509295989b509295989b509295989b565b60018060a01b038416815282602082015260606040820152600061115a6060830184614d10565b600080600080600080600060e0888a03121561512657600080fd5b873561513181614cd3565b9650602088013561514181614cd3565b955060408801359450606088013561515881614e46565b93506080880135925060a088013561516f81614e46565b915060c088013561517f81614e46565b8091505092959891949750929550565b6000806000606084860312156151a457600080fd5b83356151af81614cd3565b92506020840135915060408401356151c681614f23565b809150509250925092565b600080604083850312156151e457600080fd5b82356151ef81614cd3565b946020939093013593505050565b600080600080600060a0868803121561521557600080fd5b853561522081614cd3565b94506020860135935060408601359250606086013561523e81614e46565b9150608086013561524e81614e46565b809150509295509295909350565b600081518084526020808501945080840160005b838110156152955781516001600160a01b031687529582019590820190600101615270565b509495945050505050565b6001600160a01b0383168152604060208201819052600090610b0e9083018461525c565b634e487b7160e01b600052602160045260246000fd5b600381106152ea576152ea6152c4565b9052565b60028110610b2257610b226152c4565b6152ea816152ee565b8060005b601981101561165a578151151584526020938401939091019060010161530b565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156154af57888303603f19018552815180516001600160a01b03168452610520818901516001600160a01b038116868b01525087820151615399898701826152da565b506060808301516153ac828801826152da565b50506080808301516153c0828801826152fe565b505060a0828101516001600160a01b03169086015260c0808301519086015260e08083015164ffffffffff9081169187019190915261010080840151909116908601526101208083015115159086015261014080830151151590860152610160808301511515908601526101808083015161543d82880182615307565b50506101a08201516001600160a01b03166104a08601526101c08201516001600160601b03166104c08601526101e08201516104e0860182905261548382870182614d10565b915050610200820151915061549c6105008601836152fe565b9588019593505090860190600101615353565b509098975050505050505050565b600080600080600060a086880312156154d557600080fd5b85356154e081614cd3565b945060208601356154f081614cd3565b935060408601359250606086013561523e81614e46565b602081526000610b11602083018461525c565b6000806040838503121561552d57600080fd5b82356151ef81614e5f565b60008060006060848603121561554d57600080fd5b83359250602084013561555f81614cd3565b929592945050506040919091013590565b6000806040838503121561558357600080fd5b823561558e81614cd3565b9150602083013561559e81614f23565b809150509250929050565b6000602082840312156155bb57600080fd5b81356001600160401b038111156155d157600080fd5b8201601f810184136155e257600080fd5b6155f184823560208401614f43565b949350505050565b600064ffffffffff8085511683528060208601511660208401525060606040830152610b0e606083018461525c565b6000806040838503121561563b57600080fd5b823561564681614cd3565b9150602083013561559e81614cd3565b60008060008060008060c0878903121561566f57600080fd5b863561567a81614cd3565b9550602087013561568a81614cd3565b9450604087013561569a81614cd3565b93506060870135925060808701356156b181614e46565b915060a08701356156c181614e46565b809150509295509295509295565b6000806000606084860312156156e457600080fd5b83356156ef81614cd3565b92506020840135915060408401356001600160401b0381111561571157600080fd5b61571d86828701614f9a565b9150509250925092565b6000806040838503121561573a57600080fd5b823561574581614cd3565b915060208301356001600160581b038116811461559e57600080fd5b60006020828403121561577357600080fd5b8135610b1181614ed2565b60006020828403121561579057600080fd5b5035919050565b600060c08201905060018060a01b038084511683526001600160601b03602085015116602084015280604085015116604084015250606083015164ffffffffff8082166060850152806080860151166080850152505060a08301516157fb816152ee565b8060a08401525092915050565b600080600080600080600080610100898b03121561582557600080fd5b883561583081614cd3565b9750602089013561584081614cd3565b9650604089013561585081614cd3565b955060608901359450608089013561586781614e46565b935060a089013561587781614f23565b925060c089013561588781614ed2565b915060e089013561589781614ed2565b809150509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b6000826158cd576158cd614ca9565b500490565b8082028115828204841417611507576115076158a8565b81810381811115611507576115076158a8565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600181811c9082168061593c57607f821691505b602082108103613eb857634e487b7160e01b600052602260045260246000fd5b60006020828403121561596e57600080fd5b5051919050565b60006020828403121561598757600080fd5b8151610b1181614cd3565b80516138a981614e46565b6000602082840312156159af57600080fd5b8151610b1181614e46565b601f82111561160857600081815260208120601f850160051c810160208610156159e15750805b601f850160051c820191505b818110156122d3578281556001016159ed565b81516001600160401b03811115615a1957615a19614d69565b615a2d81615a278454615928565b846159ba565b602080601f831160018114615a625760008415615a4a5750858301515b600019600386901b1c1916600185901b1785556122d3565b600085815260208120601f198616915b82811015615a9157888601518255948401946001909101908401615a72565b5085821015615aaf5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060018201615ad157615ad16158a8565b5060010190565b600082601f830112615ae957600080fd5b81516020615af9614df383614daf565b82815260059290921b84018101918181019086841115615b1857600080fd5b8286015b84811015614e3b578051615b2f81614cd3565b8352918301918301615b1c565b600060208284031215615b4e57600080fd5b81516001600160401b03811115615b6457600080fd5b6155f184828501615ad8565b80516138a981614cd3565b600082601f830112615b8c57600080fd5b81516020615b9c614df383614daf565b82815260059290921b84018101918181019086841115615bbb57600080fd5b8286015b84811015614e3b578051615bd281614e5f565b8352918301918301615bbf565b80516138a981614ed2565b80516138a981614ef0565b80516138a981614f0b565b80516138a981614f23565b60008060008060008060008060008060006101608c8e031215615c2d57600080fd5b615c368c615b70565b9a50615c4460208d01615b70565b995060408c01516001600160401b03811115615c5f57600080fd5b615c6b8e828f01615ad8565b99505060608c01519750615c8160808d01615992565b965060a08c01516001600160401b03811115615c9c57600080fd5b615ca88e828f01615b7b565b965050615cb760c08d01615bdf565b9450615cc560e08d01615bdf565b9350615cd46101008d01615bea565b9250615ce36101208d01615bf5565b9150615cf26101408d01615c00565b90509295989b509295989b9093969950565b60006001600160601b0380841680615d1e57615d1e614ca9565b92169190910492915050565b60006001600160601b0380841680615d4457615d44614ca9565b92169190910692915050565b80820180821115611507576115076158a8565b6001600160a01b038c16815260208082018c90528a15156040830152610160606083018190528a519083018190526000916101808401918c82019190845b81811015615dc057835160ff1685529382019392820192600101615da1565b50505064ffffffffff8b1660808501525064ffffffffff891660a084015261ffff881660c0840152615df560e08401886152da565b6001600160601b038616610100840152828103610120840152615e188186614d10565b915050615e296101408301846152fe565b9c9b505050505050505050505050565b600181815b80851115615e74578160001904821115615e5a57615e5a6158a8565b80851615615e6757918102915b93841c9390800290615e3e565b509250929050565b600082615e8b57506001611507565b81615e9857506000611507565b8160018114615eae5760028114615eb857615ed4565b6001915050611507565b60ff841115615ec957615ec96158a8565b50506001821b611507565b5060208310610133831016604e8410600b8410161715615ef7575081810a611507565b615f018383615e39565b8060001904821115615f1557615f156158a8565b029392505050565b6000610b118383615e7c56fea2646970667358221220ef44aa63d9541f34cd1b89cd7aa55beefd234f08a07d838c60de8aec85654dad64736f6c63430008110033
Deployed Bytecode
0x60806040526004361061028c5760003560e01c80637be4c1771161015a578063b52d1c19116100c1578063f14210a61161007a578063f14210a614610863578063f228967e14610883578063f50ef9b4146108b0578063f7c618c1146108d0578063fc4a7db1146108f0578063fc662b1c1461091057600080fd5b8063b52d1c19146107a9578063b674d1d7146107c9578063c00206e1146107e3578063c2c97fa314610803578063d800321314610823578063df0003731461084357600080fd5b8063a1db978211610113578063a1db9782146106ef578063a4c0ed361461070f578063a5bc5b8414610722578063a659f29114610737578063a9059cbb14610757578063b30929cd1461077757600080fd5b80637be4c177146106655780637da3f6131461067a5780638546039e1461068f5780638ad2b02d146106af57806395d89b411461034157806397ec8346146106cf57600080fd5b80634a01e225116101fe5780636b33c1ef116101b75780636b33c1ef1461057657806370a082311461059657806371d55afe146105b857806377dd4ac3146105d857806379150d34146105f85780637b0a47ee1461062657600080fd5b80634a01e2251461048e5780634d0800b0146104bc57806354559dbb146104e95780635921920714610516578063652c12eb146105365780636605bfda1461055657600080fd5b806318160ddd1161025057806318160ddd146103b857806327eb8773146103d75780632a468529146103f7578063313ce5671461040c5780634144c028146104365780634815d31c1461045657600080fd5b80630186fce1146102eb5780630294bdab1461032157806306fdde0314610341578063147eb2601461037657806316ab93b11461038957600080fd5b366102e65760015461029e9034614cbf565b6000036102b1576102af3334610930565b005b6102c9335b60196a09195731e2ce35eb000000610aab565b6102af5760405163020ad41b60e11b815260040160405180910390fd5b600080fd5b3480156102f757600080fd5b5060025461030c90600160f81b900460ff1681565b60405190151581526020015b60405180910390f35b34801561032d57600080fd5b506102af61033c366004614cf3565b610b18565b34801561034d57600080fd5b50604080518082018252600681526545505341504960d01b602082015290516103189190614d56565b6102af610384366004614fba565b610b25565b34801561039557600080fd5b506103a96103a4366004614cf3565b610bfd565b604051610318939291906150e4565b3480156103c457600080fd5b506000545b604051908152602001610318565b3480156103e357600080fd5b506103c96103f236600461510b565b610cb2565b34801561040357600080fd5b506102af610e3e565b34801561041857600080fd5b50600354610100900460ff1660405160ff9091168152602001610318565b34801561044257600080fd5b5061030c61045136600461518f565b610aab565b34801561046257600080fd5b506104766104713660046151d1565b610e82565b6040516001600160a01b039091168152602001610318565b34801561049a57600080fd5b506104ae6104a93660046151fd565b610eba565b6040516103189291906152a0565b3480156104c857600080fd5b506104dc6104d7366004614cf3565b610f9d565b604051610318919061532c565b3480156104f557600080fd5b506105096105043660046154bd565b611145565b6040516103189190615507565b34801561052257600080fd5b506102af61053136600461551a565b611163565b34801561054257600080fd5b506102af610551366004614cf3565b6111ac565b34801561056257600080fd5b506102af610571366004614cf3565b6112ee565b34801561058257600080fd5b506102af610591366004615538565b611339565b3480156105a257600080fd5b506103c96105b1366004614cf3565b5060005490565b3480156105c457600080fd5b506102af6105d3366004615570565b611391565b3480156105e457600080fd5b506102af6105f33660046155a9565b61139c565b34801561060457600080fd5b50610618610613366004614cf3565b61143d565b6040516103189291906155f9565b34801561063257600080fd5b5060025461064d90600160a01b90046001600160581b031681565b6040516001600160581b039091168152602001610318565b34801561067157600080fd5b506102af6114ad565b34801561068657600080fd5b506102af6114b8565b34801561069b57600080fd5b5061030c6106aa366004615628565b6114c8565b3480156106bb57600080fd5b506102af6106ca366004615570565b61150d565b3480156106db57600080fd5b5061030c6106ea366004615656565b61154a565b3480156106fb57600080fd5b506102af61070a3660046151d1565b611566565b6102af61071d3660046156cf565b61160d565b34801561072e57600080fd5b506102af611660565b34801561074357600080fd5b506102af610752366004614cf3565b6116a0565b34801561076357600080fd5b5061030c6107723660046151d1565b6116b9565b34801561078357600080fd5b506102af336000908152600d60205260409020805469ffffffffffffffffffff19169055565b3480156107b557600080fd5b506102af6107c4366004614cf3565b611710565b3480156107d557600080fd5b5060035461030c9060ff1681565b3480156107ef57600080fd5b506102af6107fe366004614cf3565b611763565b34801561080f57600080fd5b506102af61081e366004615727565b61177c565b34801561082f57600080fd5b506102af61083e366004615761565b6117fe565b34801561084f57600080fd5b5061030c61085e366004615628565b61180e565b34801561086f57600080fd5b5061030c61087e36600461577e565b611821565b34801561088f57600080fd5b506108a361089e366004614cf3565b6118a7565b6040516103189190615797565b3480156108bc57600080fd5b506104dc6108cb366004614cf3565b61198d565b3480156108dc57600080fd5b50600254610476906001600160a01b031681565b3480156108fc57600080fd5b5061047661090b366004615808565b611b1c565b34801561091c57600080fd5b506102af61092b366004615761565b611bad565b6001600160a01b0382166000908152600f602052604081205460015490919061095990846158be565b90508181111561099957826001548361097291906158d2565b60405163ea626b3f60e01b8152600481019290925260248201526044015b60405180910390fd5b815b6000811180156109ab5750600082115b15610aa4576001600160a01b0385166000908152600f602052604081206109d36001846158e9565b815481106109e3576109e36158fc565b6000918252602080832091909101546001600160a01b031680835260098252604092839020600101805460ff60f01b1916905591518281529192507f851101b6327b058b27638fcf86d96eec48dca48ba23b1f29ed67139449f9407d910160405180910390a16001600160a01b0386166000908152600f60205260409020805480610a7057610a70615912565b600082815260209020810160001990810180546001600160a01b03191690559081019091559283019291909101905061099b565b5050505050565b60408051606080820183526001600160a01b038616825230602080840191909152600083850181905284519283018552600180845283830152828501819052845180860190955280855290840181905292610b0e92919085908790869081611bef565b90505b9392505050565b610b223382611deb565b50565b6001543414610b47576040516333b18e6b60e11b815260040160405180910390fd5b6000604051806101a001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c81526020018b81526020018a151581526020018981526020018864ffffffffff1681526020018764ffffffffff1681526020018661ffff168152602001856002811115610bc357610bc36152c4565b81526001600160601b038516602082015260408101849052606001600090529050610bee8133611e2a565b50505050505050505050505050565b600a602052600090815260409020805460018201546002830180546001600160a01b03909316939192610c2f90615928565b80601f0160208091040260200160405190810160405280929190818152602001828054610c5b90615928565b8015610ca85780601f10610c7d57610100808354040283529160200191610ca8565b820191906000526020600020905b815481529060010190602001808311610c8b57829003601f168201915b5050505050905083565b600080610cc28989898787611145565b905085610d7c5760005b8151811015610d7657886001600160a01b03166370a08231838381518110610cf657610cf66158fc565b60200260200101516040518263ffffffff1660e01b8152600401610d2991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6a919061595c565b90920191600101610ccc565b50610e31565b60005b8151811015610e2f57886001600160a01b031662fdd58e838381518110610da857610da86158fc565b6020026020010151886040518363ffffffff1660e01b8152600401610de29291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015610dff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e23919061595c565b90920191600101610d7f565b505b505b979650505050505050565b610e56335b60176a0847b32ff4cb02fc400000610aab565b610e7657604051630894d7d160e41b815260036004820152602401610990565b6003805460ff19169055565b600f6020528160005260406000208181548110610e9e57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600060606000876001600160a01b0316636352211e886040518263ffffffff1660e01b8152600401610eee91815260200190565b602060405180830381865afa158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f9190615975565b9050610f3f8189898989896122db565b90935091506001600160a01b038316610f8057610f7a81898860405180604001604052808a15151515815260200189151515158152506125c1565b90935091505b6001600160a01b038316610f92578092505b509550959350505050565b6060600060076000610fae8561288e565b815260200190815260200160002090506000610fc9826128e8565b90506000816001600160401b03811115610fe557610fe5614d69565b60405190808252806020026020018201604052801561101e57816020015b61100b614bad565b8152602001906001900390816110035790505b50905060005b8281101561113c57600061103885836128f2565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b860416608084015294955091939092909160a0840191600160f01b900460ff16908111156110d2576110d26152c4565b60018111156110e3576110e36152c4565b90525080516020820151919250611115918a90611100838761180e565b85606001518660800151888860a001516128fe565b848481518110611127576111276158fc565b60209081029190910101525050600101611024565b50949350505050565b606061115686868686866000612c04565b5090505b95945050505050565b61116c33610e43565b61118c57604051630894d7d160e41b815260036004820152602401610990565b6003805460ff9093166101000261ff001990931692909217909155600055565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b8604166080840152929391929160a0840191600160f01b90910460ff1690811115611243576112436152c4565b6001811115611254576112546152c4565b90525080519091506001600160a01b03166112825760405163a9e649e960e01b815260040160405180910390fd5b61129881602001516001600160601b0316612f1a565b15806112bf57506112bf816060015164ffffffffff16826080015164ffffffffff16612f3f565b156112dc576040516287bfad60e21b815260040160405180910390fd5b80516112ea90836000612f53565b5050565b6112f733610e43565b61131757604051630894d7d160e41b815260036004820152602401610990565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b611351335b60186a085ac218dbe29340800000610aab565b61137157604051630894d7d160e41b815260026004820152602401610990565b6001929092556001600160a01b0316600090815260106020526040902055565b6112ea338383612f53565b6113a5336102b6565b6113c557604051630894d7d160e41b815260016004820152602401610990565b60035460405163c47f002760e01b8152620100009091046001600160a01b03169063c47f0027906113fa908490600401614d56565b6020604051808303816000875af1158015611419573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ea919061595c565b604080518082018252600080825260208083018290526001600160a01b0385168252600d8152838220600e909152929020909160609161147c9061339c565b60408051808201909152915464ffffffffff8082168452650100000000009091041660208301529094909350915050565b6114b6336133a9565b565b6114b6334264ffffffffff613400565b60006114f782600760006114db8761288e565b8152602001908152602001600020611bcd90919063ffffffff16565b61150357506000611507565b5060015b92915050565b611518338383613463565b306001600160a01b038316036115415760405163e1bbc9d760e01b815260040160405180910390fd5b6112ea3361348b565b600061155a87868686868b612c04565b98975050505050505050565b61156f336102b6565b61158f57604051630894d7d160e41b815260016004820152602401610990565b6004805460405163a9059cbb60e01b81526001600160a01b03918216928101929092526024820183905283169063a9059cbb906044016020604051808303816000875af11580156115e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611608919061599d565b505050565b3360009081526010602052604090205480158061162a5750828114155b1561164857604051632ab209a560e11b815260040160405180910390fd5b61165a611654836134db565b85611e2a565b50505050565b61166933610e43565b61168957604051630894d7d160e41b815260036004820152602401610990565b600280546001600160f81b0316600160f81b179055565b336000908152600e602052604090206112ea9082611bb8565b60006116c633848461364a565b604051600081526001600160a01b0384169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a350600192915050565b611719336102b6565b61173957604051630894d7d160e41b815260016004820152602401610990565b600380546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b336000908152600e602052604090206112ea90826137c6565b6117853361133e565b6117a557604051630894d7d160e41b815260026004820152602401610990565b600280546001600160a01b0319166001600160a01b0384161790819055600160f81b900460ff166112ea57600280546001600160581b038316600160a01b026affffffffffffffffffffff60a01b199091161790555050565b610b22338264ffffffffff613400565b60006114f782600660006114db876137db565b600061182c336102b6565b61184c57604051630894d7d160e41b815260016004820152602401610990565b6004546040516001600160a01b03909116908390600081818185875af1925050503d8060008114611899576040519150601f19603f3d011682016040523d82523d6000602084013e61189e565b606091505b50909392505050565b6118dd6040805160c08101825260008082526020820181905291810182905260608101829052608081018290529060a082015290565b6001600160a01b03828116600090815260096020908152604091829020825160c08101845281548086168252600160a01b908190046001600160601b0316938201939093526001808301549586169482019490945291840464ffffffffff9081166060840152600160c81b85041660808301529092909160a0840191600160f01b900460ff1690811115611973576119736152c4565b6001811115611984576119846152c4565b90525092915050565b606060006006600061199e856137db565b8152602001908152602001600020905060006119b9826128e8565b90506000816001600160401b038111156119d5576119d5614d69565b604051908082528060200260200182016040528015611a0e57816020015b6119fb614bad565b8152602001906001900390816119f35790505b50905060005b8281101561113c576000611a2885836128f2565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b860416608084015294955091939092909160a0840191600160f01b900460ff1690811115611ac257611ac26152c4565b6001811115611ad357611ad36152c4565b815250509050611af588826040015183602001516111008560400151876114c8565b848481518110611b0757611b076158fc565b60209081029190910101525050600101611a14565b604080516060998a1b6001600160601b0319908116602080840191909152998b1b811660348301529790991b9096166048890152605c88019490945291151560f81b607c87015260a01b6001600160a01b031916607d86015260d890811b6001600160d81b0319908116608987015291901b16608e8401528051607381850301815260939093019052815191012090565b610b22334283613400565b6000610b11836001600160a01b03841661381c565b6001600160a01b03811660009081526001830160205260408120541515610b11565b8551600090158015611c2357506001611c10876001600160601b031661386b565b6002811115611c2157611c216152c4565b145b80611c5d57508660200151158015611c5d57506002611c4a876001600160601b031661386b565b6002811115611c5b57611c5b6152c4565b145b80611c785750611c7685876001600160601b03166138ae565b155b15611c8557506000610e33565b6000611caf89600001518a602001518b60400151888c604001518c8a600001518b60200151611b1c565b9050611cbf8960200151826114c8565b1580611cd457508851611cd2908261180e565b155b80611d16575060016001600160a01b0382166000908152600960205260409020600190810154600160f01b900460ff1690811115611d1457611d146152c4565b145b80611d5c5750611d2e876001600160601b03166138e5565b8015611d5c57506040808a01516001600160a01b038381166000908152600a60205292909220548216911614155b80611d9d5750611d74876001600160601b0316612f1a565b8015611d9d5750611d9b846000015164ffffffffff16856020015164ffffffffff16612f3f565b155b80611dcd57506001600160a01b03831615801590611dcd5750806001600160a01b0316836001600160a01b031614155b15611ddc576000915050610e33565b50600198975050505050505050565b611df58282613903565b15611dfe575050565b611e088183613903565b15611e11575050565b60405163a9e649e960e01b815260040160405180910390fd5b60005b82604001515181101561221457611e5383600001518460200151856101400151856139fd565b6000611e9f846020015185604001518481518110611e7357611e736158fc565b6020026020010151866060015187608001518860a001518960c001518a60e001518b6101200151613a30565b90506000611ee88560000151866020015187604001518681518110611ec657611ec66158fc565b602002602001015188606001518960800151878b60c001518c60e00151611b1c565b9050846080015115611f4a57611f488160086000611f2c89602001518a604001518981518110611f1a57611f1a6158fc565b60200260200101518b60600151613cbf565b8152602001908152602001600020611bb890919063ffffffff16565b505b60006001600160a01b031685604001518481518110611f6b57611f6b6158fc565b60200260200101516001600160a01b0316141580611f8e57506101608501515115155b1561202757604051806060016040528086604001518581518110611fb457611fb46158fc565b6020908102919091018101516001600160a01b0390811683526060890151838301526101608901516040938401528481166000908152600a8352839020845181546001600160a01b03191692169190911781559083015160018201559082015160028201906120239082615a00565b5050505b60018561018001516001811115612040576120406152c4565b0361208a576020858101516001600160a01b039081166000908152600f835260408120805460018101825590825292902090910180546001600160a01b0319169183169190911790555b61209f8160066000611f2c89600001516137db565b506120b58160076000611f2c896020015161288e565b506040518060c0016040528086600001516001600160a01b03168152602001836001600160601b0316815260200186602001516001600160a01b031681526020018660c0015164ffffffffff1681526020018660e0015164ffffffffff168152602001866101800151600181111561212f5761212f6152c4565b90526001600160a01b03828116600090815260096020908152604091829020845191850151918416600160a01b6001600160601b039093168302178155918401516001808401805460608801516080890151949097166001600160c81b03199091161764ffffffffff9687169094029390931764ffffffffff60c81b198116600160c81b9690931695909502918217835560a0860151939465ffffffffffff60c81b191660ff60f01b199092169190911790600160f01b9084908111156121f8576121f86152c4565b021790555090505061220a8584613d29565b5050600101611e2d565b506002546001600160a01b0316156112ea576000826101800151600181111561223f5761223f6152c4565b036112ea576002546001600160a01b0316632e6f2136336040850151516002546122799190600160a01b90046001600160581b03166158d2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156122bf57600080fd5b505af11580156122d3573d6000803e3d6000fd5b505050505050565b600060606000600860006122f08b8b8b613cbf565b81526020019081526020016000209050600061230b826128e8565b90506000816001600160401b0381111561232757612327614d69565b604051908082528060200260200182016040528015612350578160200160208202803683370190505b50935060005b8281101561259f57600060098161236d87856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff1690811115612401576124016152c4565b6001811115612412576124126152c4565b8152505090506124c1604051806060016040528083600001516001600160a01b031681526020018f6001600160a01b031681526020018e6001600160a01b031681525060405180606001604052808c151581526020018b151581526020016001151581525083602001518d8f6040518060400160405280886060015164ffffffffff168152602001886080015164ffffffffff168152506124bc898d6128f290919063ffffffff16565b611bef565b158061251357506001600960006124d888866128f2565b6001600160a01b031681526020810191909152604001600020600190810154600160f01b900460ff1690811115612511576125116152c4565b145b1561251e575061258d565b600161253682602001516001600160601b031661386b565b6002811115612547576125476152c4565b14612555578051965061258b565b806000015186848151811061256c5761256c6158fc565b6001600160a01b03909216602092830291909101909101526001909201915b505b8061259781615abf565b915050612356565b50808211156125b2578351818303900384525b5050505b965096945050505050565b600060606000600760006125d48961288e565b8152602001908152602001600020905060006125ef826128e8565b6001600160401b0381111561260657612606614d69565b60405190808252806020026020018201604052801561262f578160200160208202803683370190505b50925060005b61263e836128e8565b81101561288257600060098161265486856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff16908111156126e8576126e86152c4565b60018111156126f9576126f96152c4565b815250509050600061271782602001516001600160601b03166138e5565b1561271f5750885b604080516060808201835284516001600160a01b0390811683528e811660208085019190915290851683850152835180830185528c51151581528c82015115158183015260008186018190528288015186518088019097529388015164ffffffffff9081168752608089015116928601929092526127a6949092918e916124bc8c8b6128f2565b15806127f457506127c382602001516001600160601b03166138e5565b1580156127f457506127f489600560006127e08f8f600080613dde565b8152602001908152602001600020546138ae565b15612800575050612870565b600161281883602001516001600160601b031661386b565b6002811115612829576128296152c4565b14612837578151965061286d565b816000015186858151811061284e5761284e6158fc565b6001600160a01b03909216602092830291909101909101526001909301925b50505b8061287a81615abf565b915050612635565b50505094509492505050565b6001600160a01b0381166000908152600c602090815260408083205490516001600160601b0319606086901b169281019290925260348201526054015b604051602081830303815290604052805190602001209050919050565b6000611507825490565b6000610b118383613e53565b612906614bad565b6001600160a01b038084166000908152600a602090815260408083208151606081018352815490951685526001810154928501929092526002820180549394939184019161295390615928565b80601f016020809104026020016040519081016040528092919081815260200182805461297f90615928565b80156129cc5780601f106129a1576101008083540402835291602001916129cc565b820191906000526020600020905b8154815290600101906020018083116129af57829003601f168201915b50505050508152505090506040518061022001604052808b6001600160a01b031681526020018a6001600160a01b03168152602001612a138a6001600160601b0316613e7d565b6002811115612a2457612a246152c4565b8152602001612a3b8a6001600160601b031661386b565b6002811115612a4c57612a4c6152c4565b8152602001612a638a6001600160601b0316613ebe565b6001811115612a7457612a746152c4565b815260200182600001516001600160a01b03168152602001826020015181526020018764ffffffffff1681526020018664ffffffffff168152602001612ac28a6001600160601b0316612f1a565b1580612ae15750612ae18864ffffffffff168864ffffffffff16612f3f565b1515815288151560208201526040016002612b048b6001600160601b0316613e7d565b6002811115612b1557612b156152c4565b141580612b9c5750825160208401516040516331a9108f60e11b815260048101919091526001600160a01b038d8116921690636352211e90602401602060405180830381865afa158015612b6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b919190615975565b6001600160a01b0316145b15158152602001612bb58a6001600160601b0316613ee2565b8152602001856001600160a01b03168152602001896001600160601b0316815260200182604001518152602001846001811115612bf457612bf46152c4565b90529a9950505050505050505050565b60606000612c1d86600560006127e08c8c600080613dde565b80612c4c57506001600160a01b03871615801590612c4c5750612c4c86600560006127e08c6000806000613dde565b15612c6e5784612c6e57505060408051600080825260208201909252906125b6565b600080612cb260405180606001604052808c6001600160a01b03168152602001876001600160a01b031681526020018b6001600160a01b0316815250898989613f2e565b929650919450925090508215612cc95750506125b6565b80821115612cdb578351818303900384525b60035460ff168015612cee575083516001145b15612f09576040516354559dbb60e01b81526001600160a01b03808c1660048301528a16602482015260448101899052871515606482015286151560848201526000907388888888888806458312bb6b7ae0f9a7ad30ea40906354559dbb9060a401600060405180830381865afa158015612d6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d959190810190615b3c565b9050600181511115612f0757612dca81600181518110612db757612db76158fc565b602002602001015160008060008d613f82565b80612df85750612df881600181518110612de657612de66158fc565b60200260200101518b6000808d613f82565b15612e0a5750600092506125b6915050565b856001600160a01b031681600181518110612e2757612e276158fc565b60200260200101516001600160a01b031603612e4a5750600192506125b6915050565b604080516002808252606082018352909160208301908036833701905050945080600081518110612e7d57612e7d6158fc565b602002602001015185600081518110612e9857612e986158fc565b60200260200101906001600160a01b031690816001600160a01b03168152505080600181518110612ecb57612ecb6158fc565b602002602001015185600181518110612ee657612ee66158fc565b60200260200101906001600160a01b031690816001600160a01b0316815250505b505b506000915050965096945050505050565b60006001612f2783613ebe565b6001811115612f3857612f386152c4565b1492915050565b60004283108015610b115750504210919050565b6001600160a01b038281166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b8604166080840152929391929160a0840191600160f01b90910460ff1690811115612fea57612fea6152c4565b6001811115612ffb57612ffb6152c4565b90525080519091506001600160a01b038581169116146130245761302484826040015184613463565b600261303c82602001516001600160601b0316613e7d565b600281111561304d5761304d6152c4565b036131e5576001600160a01b038084166000908152600a602090815260408083208151606081018352815490951685526001810154928501929092526002820180549394939184019161309f90615928565b80601f01602080910402602001604051908101604052809291908181526020018280546130cb90615928565b80156131185780601f106130ed57610100808354040283529160200191613118565b820191906000526020600020905b8154815290600101906020018083116130fb57829003601f168201915b5050505050815250509050600061313c836040015183600001518460200151613cbf565b60008181526008602052604090209091506131579086611bcd565b6131745760405163a9e649e960e01b815260040160405180910390fd5b600081815260086020526040902061318c90866137c6565b80156131bf575060016131ab84602001516001600160601b031661386b565b60028111156131bc576131bc6152c4565b14155b156131e2576131e283604001518360000151600185602001518760200151613fdf565b50505b61321683600660006131fa85600001516137db565b81526020019081526020016000206137c690919063ffffffff16565b5061322c83600760006131fa856040015161288e565b801561325f5750600161324b82602001516001600160601b031661386b565b600281111561325c5761325c6152c4565b14155b80156132925750600261327e82602001516001600160601b0316613e7d565b600281111561328f5761328f6152c4565b14155b156132e95760006132af82602001516001600160601b03166138e5565b156132d157506001600160a01b038084166000908152600a6020526040902054165b6132e78260400151826000808660200151613fdf565b505b6001600160a01b0383166000908152600960209081526040808320838155600190810180546001600160f81b0319169055600a909252822080546001600160a01b0319168155908101829055906133436002830182614c37565b5050805160408083015181516001600160a01b039384168152908316602082015291851682820152517f59ae3c34e9447e6c9676b72ba973ce1e412d1051a6da544ac93e2a07ef04259b9181900360600190a150505050565b60606000610b1183614044565b6001600160a01b0381166000818152600b60209081526040918290208054600101905590519182527f17847ea98d58f1bba43d4d7add9ace4b715eb6374a39c43445d322b747d6001991015b60405180910390a150565b60408051808201825264ffffffffff938416815291831660208084019182526001600160a01b039095166000908152600d90955293209051815493518316650100000000000269ffffffffffffffffffff19909416921691909117919091179055565b61346e8383836140a0565b6116085760405163fed82dc360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600c60209081526040918290208054600101905590519182527f150d16c5ed87101ded5915d2c85572217aa147e5f50f384305123e8c6c5680da91016133f5565b604080516101a08101825260008082526020820181905260609282018390528282018190526080820181905260a0820183905260c0820181905260e0820181905261010082018190526101208201819052610140820181905261016082019290925261018081019190915260008060008060008060008060008060008c80602001905181019061356b9190615c0b565b9a509a509a509a509a509a509a509a509a509a509a50604051806101a001604052808c6001600160a01b031681526020018b6001600160a01b031681526020018a815260200189815260200188151581526020018781526020018664ffffffffff1681526020018564ffffffffff1681526020018461ffff1681526020018360028111156135fb576135fb6152c4565b8152602001826001600160601b0316815260200160405180602001604052806000815250815260200160006001811115613637576136376152c4565b90529d9c50505050505050505050505050565b606081901c816000600a6136606103e884615d04565b61366a9190615d2a565b6001600160601b0316905060018103613695576122d3858785856001600160601b0316600080614124565b600281036136c6576001600160a01b0383166136ba576136b58686611deb565b6122d3565b6122d386846000612f53565b600381036136d7576122d3866133a9565b600481036136e8576122d38661348b565b60058103613700576122d3864264ffffffffff613400565b60068103613739575050506001600160a01b039092166000908152600d60205260409020805469ffffffffffffffffffff191690555050565b6007810361375a576122d3858785856001600160601b031660016000614124565b60088103613786576122d38587856001600160601b03861660006137814262278d00615d50565b614124565b600981036137ad576122d38587856001600160601b0386166000613781426276a700615d50565b604051631ec9ca4160e21b815260040160405180910390fd5b6000610b11836001600160a01b038416614382565b6001600160a01b0381166000908152600b602090815260408083205490516001600160601b0319606086901b169281019290925260348201526054016128cb565b600081815260018301602052604081205461386357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611507565b506000611507565b6000613878601a83614475565b60000361388757506000919050565b613892601a83614475565b6001036138a157506001919050565b506002919050565b919050565b6000600e83141580156138c757506138c76001836144c5565b156138d457506001611507565b6138de83836144c5565b9050611507565b600060016138f283613e7d565b6002811115612f3857612f386152c4565b60008061391a848460008060006001600080611b1c565b6001600160a01b038181166000908152600960209081526040808320815160c08101835281548087168252600160a01b908190046001600160601b0316948201949094526001808301549687169382019390935292850464ffffffffff9081166060850152600160c81b860416608084015294955091939092909160a0840191600160f01b900460ff16908111156139b4576139b46152c4565b60018111156139c5576139c56152c4565b90525080519091506001600160a01b0316156139f2576139e785836000612f53565b600192505050611507565b506000949350505050565b613a0784846144db565b15613a2557604051630da1844d60e01b815260040160405180910390fd5b61165a818484613463565b6000806001600160a01b03891615613b05578615613af3576040516331a9108f60e11b8152600481018990526001600160a01b03808c1691908b1690636352211e90602401602060405180830381865afa158015613a92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab69190615975565b6001600160a01b031614613add5760405163400d9f5560e11b815260040160405180910390fd5b6b06765c793fa10079d000000082019150613b05565b6b033b2e3c9fd0803ce8000000820191505b6001836002811115613b1957613b196152c4565b03613b2f576a084595161401484a000000820191505b6002836002811115613b4357613b436152c4565b03613b59576a108b2a2c28029094000000820191505b64ffffffffff8585011615613b79576a52b7d2dcc80cd2e4000000820191505b60005b8651811015613c6f576001846002811115613b9957613b996152c4565b14158015613bcb5750613bcb8b8b8a8c8b8681518110613bbb57613bbb6158fc565b602002602001015160ff16613f82565b15613c0d57868181518110613be257613be26158fc565b6020026020010151604051630aab3ce760e41b8152600401610990919060ff91909116815260200190565b868181518110613c1f57613c1f6158fc565b602002602001015160ff16600103613c3c57600182019150613c67565b6001878281518110613c5057613c506158fc565b60200260200101510360ff16600a0a600102820191505b600101613b7c565b506001836002811115613c8457613c846152c4565b14613cb2578060056000613c9a8d8d8c8e613dde565b81526020810191909152604001600020805490910190555b0198975050505050505050565b6001600160a01b0383166000908152600c60209081526040918290205482516001600160601b0319606097881b81168285015260348201929092529490951b9094166054840152606880840192909252805180840390920182526088909201909152805191012090565b81602001516001600160a01b031682600001516001600160a01b03167f44d84a2c5d27e81636e3182f4601b82564c8086c61dd9a83e3b4586c4db96b2f84604001518481518110613d7c57613d7c6158fc565b6020026020010151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e6101800151604051613dd29b9a99989796959493929190615d63565b60405180910390a35050565b6001600160a01b0384166000908152600c60209081526040918290205482516001600160601b0319606098891b8116828501529690971b909516603487015292151560f81b60488601526049850191909152606980850193909352805180850390930183526089909301909252805191012090565b6000826000018281548110613e6a57613e6a6158fc565b9060005260206000200154905092915050565b600080613e8b601c84614475565b905080600003613e9e5750600092915050565b80600103613eaf5750600192915050565b50600292915050565b50919050565b6000613ecb601b83614475565b600003613eda57506000919050565b506001919050565b613eea614c71565b60005b6019811015613eb857613f0a613f04826001615d50565b8461457a565b828260198110613f1c57613f1c6158fc565b91151560209092020152600101613eed565b60606000806000806001600160a01b031688604001516001600160a01b031603613f6b57613f5e88888888614586565b9350935093509350613f77565b613f5e88888888614868565b945094509450949050565b60008060056000613f9589898989613dde565b815260200190815260200160002054905080600014158015613fc657508260011480613fc65750613fc683826138ae565b15613fd557600191505061115a565b600091505061115a565b6000613fed86868686613dde565b9050613ffb6019601d6158e9565b61400690600a615f1d565b614019906001600160601b038416614cbf565b600082815260056020526040812080549091906140379084906158e9565b9091555050505050505050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561409457602002820191906000526020600020905b815481526020019060010190808311614080575b50505050509050919050565b6000836001600160a01b0316836001600160a01b0316036140c357506001610b11565b60408051606080820183526001600160a01b03808816835286166020808401919091526000838501819052845192830185526001808452838301528285018190528451808601909552808552908401819052610b0e938691600e9181611bef565b6040805160018082528183019092526000916020808301908036833701905050905060006141546103e886614cbf565b9050858260008151811061416a5761416a6158fc565b6001600160a01b0390921660209283029190910190910152600061271061419e6c01431e0fae6d7217caa000000088614cbf565b6141a891906158be565b905060006001546000146141ba575060015b6060826000036142125760408051600180825281830190925290602080830190803683370190505090506001816000815181106141f9576141f96158fc565b602002602001019060ff16908160ff16815250506142b1565b6040805160198082526103408201909252600091602082016103208036833701905050915060005b601981101561429a57614257614251826001615d50565b8661457a565b1561429257614267816001615d50565b838381518110614279576142796158fc565b60ff909216602092830291909101909101526001909101905b60010161423a565b5080601911156142af57815181016018190182525b505b614375604051806101a001604052808d6001600160a01b031681526020018c6001600160a01b0316815260200187815260200160008152602001600015158152602001838152602001600064ffffffffff1681526020018864ffffffffff1681526020018661ffff168152602001896002811115614331576143316152c4565b815260200160006001600160601b0316815260200160405180602001604052806000815250815260200184600181111561436d5761436d6152c4565b90528b611e2a565b5050505050505050505050565b6000818152600183016020526040812054801561446b5760006143a66001836158e9565b85549091506000906143ba906001906158e9565b905081811461441f5760008660000182815481106143da576143da6158fc565b90600052602060002001549050808760000184815481106143fd576143fd6158fc565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061443057614430615912565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611507565b6000915050611507565b60008061448384600a615f1d565b9050600084600103614497575060016144b0565b6144a26001866158e9565b6144ad90600a615f1d565b90505b806144bb8386614cbf565b61115a91906158be565b60006144d18383614475565b6001149392505050565b6001600160a01b0382166000908152600d6020908152604080832081518083019092525464ffffffffff80821683526501000000000090910416918101829052904211806145305750805164ffffffffff1642105b1561453f576000915050611507565b6001600160a01b0384166000908152600e602052604090206145619084611bcd565b15614570576000915050611507565b5060019392505050565b6000610b1183836144c5565b60606000806000806006600061459f8b600001516137db565b815260200190815260200160002090506145b8816128e8565b6001019350836001600160401b038111156145d5576145d5614d69565b6040519080825280602002602001820160405280156145fe578160200160208202803683370190505b509450886000015185600081518110614619576146196158fc565b6001600160a01b039092166020928302919091019091015260019092019160005b6146456001866158e9565b81101561485757600060098161465b85856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff16908111156146ef576146ef6152c4565b6001811115614700576147006152c4565b81525050905061471c81602001516001600160601b03166138e5565b806147ce57506147cc60405180606001604052808d600001516001600160a01b0316815260200183604001516001600160a01b0316815260200160006001600160a01b031681525060405180606001604052808c151581526020018b151581526020016000151581525083602001518d60006040518060400160405280886060015164ffffffffff168152602001886080015164ffffffffff168152506124bc898b6128f290919063ffffffff16565b155b156147d95750614845565b8a602001516001600160a01b031681604001516001600160a01b03160361480e57506000945084935060019250613f77915050565b8060400151878681518110614825576148256158fc565b6001600160a01b0390921660209283029190910190910152506001909301925b8061484f81615abf565b91505061463a565b506000915050945094509450949050565b6060600080600080600660006148818b600001516137db565b8152602001908152602001600020905061489a816128e8565b6001019350836001600160401b038111156148b7576148b7614d69565b6040519080825280602002602001820160405280156148e0578160200160208202803683370190505b5094508860000151856000815181106148fb576148fb6158fc565b6001600160a01b039092166020928302919091019091015260019092019160005b6149276001866158e9565b81101561485757600060098161493d85856128f2565b6001600160a01b0390811682526020808301939093526040918201600020825160c08101845281548084168252600160a01b908190046001600160601b0316958201959095526001808301549384169482019490945293820464ffffffffff9081166060860152600160c81b83041660808501529160a0840191600160f01b900460ff16908111156149d1576149d16152c4565b60018111156149e2576149e26152c4565b905250905060026149ff82602001516001600160601b0316613e7d565b6002811115614a1057614a106152c4565b03614a1b5750614b84565b6000614a3382602001516001600160601b03166138e5565b15614a43575060408b0151614a62565b614a5682604001518d604001518d614b96565b15614a62575050614b84565b614b0b60405180606001604052808e600001516001600160a01b0316815260200184604001516001600160a01b03168152602001836001600160a01b031681525060405180606001604052808d151581526020018c151581526020016000151581525084602001518e60006040518060400160405280896060015164ffffffffff168152602001896080015164ffffffffff168152506124bc8a8c6128f290919063ffffffff16565b614b16575050614b84565b8b602001516001600160a01b031682604001516001600160a01b031603614b4c57506000955085945060019350613f7792505050565b8160400151888781518110614b6357614b636158fc565b6001600160a01b039092166020928302919091019091015250506001909301925b80614b8e81615abf565b91505061491c565b6000610b0e82600560006127e08888600080613dde565b604080516102208101825260008082526020820181905290918201908152602001600081526020016000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e082015261010001614c16614c71565b81526000602082018190526040820181905260608083015260809091015290565b508054614c4390615928565b6000825580601f10614c53575050565b601f016020900490600052602060002090810190610b229190614c90565b6040518061032001604052806019906020820280368337509192915050565b5b80821115614ca55760008155600101614c91565b5090565b634e487b7160e01b600052601260045260246000fd5b600082614cce57614cce614ca9565b500690565b6001600160a01b0381168114610b2257600080fd5b80356138a981614cd3565b600060208284031215614d0557600080fd5b8135610b1181614cd3565b6000815180845260005b81811015614d3657602081850181015186830182015201614d1a565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b116020830184614d10565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614da757614da7614d69565b604052919050565b60006001600160401b03821115614dc857614dc8614d69565b5060051b60200190565b600082601f830112614de357600080fd5b81356020614df8614df383614daf565b614d7f565b82815260059290921b84018101918181019086841115614e1757600080fd5b8286015b84811015614e3b578035614e2e81614cd3565b8352918301918301614e1b565b509695505050505050565b8015158114610b2257600080fd5b80356138a981614e46565b60ff81168114610b2257600080fd5b600082601f830112614e7f57600080fd5b81356020614e8f614df383614daf565b82815260059290921b84018101918181019086841115614eae57600080fd5b8286015b84811015614e3b578035614ec581614e5f565b8352918301918301614eb2565b64ffffffffff81168114610b2257600080fd5b80356138a981614ed2565b61ffff81168114610b2257600080fd5b80356138a981614ef0565b60038110610b2257600080fd5b80356138a981614f0b565b6001600160601b0381168114610b2257600080fd5b80356138a981614f23565b60006001600160401b03831115614f5c57614f5c614d69565b614f6f601f8401601f1916602001614d7f565b9050828152838383011115614f8357600080fd5b828260208301376000602084830101529392505050565b600082601f830112614fab57600080fd5b610b1183833560208501614f43565b6000806000806000806000806000806000806101808d8f031215614fdd57600080fd5b614fe68d614ce8565b9b50614ff460208e01614ce8565b9a506001600160401b0360408e0135111561500e57600080fd5b61501e8e60408f01358f01614dd2565b995060608d0135985061503360808e01614e54565b97506001600160401b0360a08e0135111561504d57600080fd5b61505d8e60a08f01358f01614e6e565b965061506b60c08e01614ee5565b955061507960e08e01614ee5565b94506150886101008e01614f00565b93506150976101208e01614f18565b92506150a66101408e01614f38565b91506001600160401b036101608e013511156150c157600080fd5b6150d28e6101608f01358f01614f9a565b90509295989b509295989b509295989b565b60018060a01b038416815282602082015260606040820152600061115a6060830184614d10565b600080600080600080600060e0888a03121561512657600080fd5b873561513181614cd3565b9650602088013561514181614cd3565b955060408801359450606088013561515881614e46565b93506080880135925060a088013561516f81614e46565b915060c088013561517f81614e46565b8091505092959891949750929550565b6000806000606084860312156151a457600080fd5b83356151af81614cd3565b92506020840135915060408401356151c681614f23565b809150509250925092565b600080604083850312156151e457600080fd5b82356151ef81614cd3565b946020939093013593505050565b600080600080600060a0868803121561521557600080fd5b853561522081614cd3565b94506020860135935060408601359250606086013561523e81614e46565b9150608086013561524e81614e46565b809150509295509295909350565b600081518084526020808501945080840160005b838110156152955781516001600160a01b031687529582019590820190600101615270565b509495945050505050565b6001600160a01b0383168152604060208201819052600090610b0e9083018461525c565b634e487b7160e01b600052602160045260246000fd5b600381106152ea576152ea6152c4565b9052565b60028110610b2257610b226152c4565b6152ea816152ee565b8060005b601981101561165a578151151584526020938401939091019060010161530b565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156154af57888303603f19018552815180516001600160a01b03168452610520818901516001600160a01b038116868b01525087820151615399898701826152da565b506060808301516153ac828801826152da565b50506080808301516153c0828801826152fe565b505060a0828101516001600160a01b03169086015260c0808301519086015260e08083015164ffffffffff9081169187019190915261010080840151909116908601526101208083015115159086015261014080830151151590860152610160808301511515908601526101808083015161543d82880182615307565b50506101a08201516001600160a01b03166104a08601526101c08201516001600160601b03166104c08601526101e08201516104e0860182905261548382870182614d10565b915050610200820151915061549c6105008601836152fe565b9588019593505090860190600101615353565b509098975050505050505050565b600080600080600060a086880312156154d557600080fd5b85356154e081614cd3565b945060208601356154f081614cd3565b935060408601359250606086013561523e81614e46565b602081526000610b11602083018461525c565b6000806040838503121561552d57600080fd5b82356151ef81614e5f565b60008060006060848603121561554d57600080fd5b83359250602084013561555f81614cd3565b929592945050506040919091013590565b6000806040838503121561558357600080fd5b823561558e81614cd3565b9150602083013561559e81614f23565b809150509250929050565b6000602082840312156155bb57600080fd5b81356001600160401b038111156155d157600080fd5b8201601f810184136155e257600080fd5b6155f184823560208401614f43565b949350505050565b600064ffffffffff8085511683528060208601511660208401525060606040830152610b0e606083018461525c565b6000806040838503121561563b57600080fd5b823561564681614cd3565b9150602083013561559e81614cd3565b60008060008060008060c0878903121561566f57600080fd5b863561567a81614cd3565b9550602087013561568a81614cd3565b9450604087013561569a81614cd3565b93506060870135925060808701356156b181614e46565b915060a08701356156c181614e46565b809150509295509295509295565b6000806000606084860312156156e457600080fd5b83356156ef81614cd3565b92506020840135915060408401356001600160401b0381111561571157600080fd5b61571d86828701614f9a565b9150509250925092565b6000806040838503121561573a57600080fd5b823561574581614cd3565b915060208301356001600160581b038116811461559e57600080fd5b60006020828403121561577357600080fd5b8135610b1181614ed2565b60006020828403121561579057600080fd5b5035919050565b600060c08201905060018060a01b038084511683526001600160601b03602085015116602084015280604085015116604084015250606083015164ffffffffff8082166060850152806080860151166080850152505060a08301516157fb816152ee565b8060a08401525092915050565b600080600080600080600080610100898b03121561582557600080fd5b883561583081614cd3565b9750602089013561584081614cd3565b9650604089013561585081614cd3565b955060608901359450608089013561586781614e46565b935060a089013561587781614f23565b925060c089013561588781614ed2565b915060e089013561589781614ed2565b809150509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b6000826158cd576158cd614ca9565b500490565b8082028115828204841417611507576115076158a8565b81810381811115611507576115076158a8565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600181811c9082168061593c57607f821691505b602082108103613eb857634e487b7160e01b600052602260045260246000fd5b60006020828403121561596e57600080fd5b5051919050565b60006020828403121561598757600080fd5b8151610b1181614cd3565b80516138a981614e46565b6000602082840312156159af57600080fd5b8151610b1181614e46565b601f82111561160857600081815260208120601f850160051c810160208610156159e15750805b601f850160051c820191505b818110156122d3578281556001016159ed565b81516001600160401b03811115615a1957615a19614d69565b615a2d81615a278454615928565b846159ba565b602080601f831160018114615a625760008415615a4a5750858301515b600019600386901b1c1916600185901b1785556122d3565b600085815260208120601f198616915b82811015615a9157888601518255948401946001909101908401615a72565b5085821015615aaf5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060018201615ad157615ad16158a8565b5060010190565b600082601f830112615ae957600080fd5b81516020615af9614df383614daf565b82815260059290921b84018101918181019086841115615b1857600080fd5b8286015b84811015614e3b578051615b2f81614cd3565b8352918301918301615b1c565b600060208284031215615b4e57600080fd5b81516001600160401b03811115615b6457600080fd5b6155f184828501615ad8565b80516138a981614cd3565b600082601f830112615b8c57600080fd5b81516020615b9c614df383614daf565b82815260059290921b84018101918181019086841115615bbb57600080fd5b8286015b84811015614e3b578051615bd281614e5f565b8352918301918301615bbf565b80516138a981614ed2565b80516138a981614ef0565b80516138a981614f0b565b80516138a981614f23565b60008060008060008060008060008060006101608c8e031215615c2d57600080fd5b615c368c615b70565b9a50615c4460208d01615b70565b995060408c01516001600160401b03811115615c5f57600080fd5b615c6b8e828f01615ad8565b99505060608c01519750615c8160808d01615992565b965060a08c01516001600160401b03811115615c9c57600080fd5b615ca88e828f01615b7b565b965050615cb760c08d01615bdf565b9450615cc560e08d01615bdf565b9350615cd46101008d01615bea565b9250615ce36101208d01615bf5565b9150615cf26101408d01615c00565b90509295989b509295989b9093969950565b60006001600160601b0380841680615d1e57615d1e614ca9565b92169190910492915050565b60006001600160601b0380841680615d4457615d44614ca9565b92169190910692915050565b80820180821115611507576115076158a8565b6001600160a01b038c16815260208082018c90528a15156040830152610160606083018190528a519083018190526000916101808401918c82019190845b81811015615dc057835160ff1685529382019392820192600101615da1565b50505064ffffffffff8b1660808501525064ffffffffff891660a084015261ffff881660c0840152615df560e08401886152da565b6001600160601b038616610100840152828103610120840152615e188186614d10565b915050615e296101408301846152fe565b9c9b505050505050505050505050565b600181815b80851115615e74578160001904821115615e5a57615e5a6158a8565b80851615615e6757918102915b93841c9390800290615e3e565b509250929050565b600082615e8b57506001611507565b81615e9857506000611507565b8160018114615eae5760028114615eb857615ed4565b6001915050611507565b60ff841115615ec957615ec96158a8565b50506001821b611507565b5060208310610133831016604e8410600b8410161715615ef7575081810a611507565b615f018383615e39565b8060001904821115615f1557615f156158a8565b029392505050565b6000610b118383615e7c56fea2646970667358221220ef44aa63d9541f34cd1b89cd7aa55beefd234f08a07d838c60de8aec85654dad64736f6c63430008110033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.