Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ERC721Facet
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; // Import necessary libraries and contracts import { AccessControlInternal } from "@solidstate/contracts/access/access_control/AccessControlInternal.sol"; import { ERC165BaseInternal } from "@solidstate/contracts/introspection/ERC165/base/ERC165BaseInternal.sol"; import { ERC721Base } from "@solidstate/contracts/token/ERC721/base/ERC721Base.sol"; import { ERC721BaseInternal } from "@solidstate/contracts/token/ERC721/base/ERC721BaseInternal.sol"; import { ERC721Enumerable } from "@solidstate/contracts/token/ERC721/enumerable/ERC721Enumerable.sol"; import { ERC721Metadata } from "@solidstate/contracts/token/ERC721/metadata/ERC721Metadata.sol"; import { PartiallyPausableInternal } from "@solidstate/contracts/security/partially_pausable/PartiallyPausableInternal.sol"; import { PausableInternal } from "@solidstate/contracts/security/pausable/PausableInternal.sol"; import "../libraries/LibSilksHorseDiamond.sol"; /** * @title ERC721Facet * @dev A Solidity smart contract representing the ERC721 facet of the SilksHorseDiamond contract. * This facet provides functionality for purchasing and airdropping NFTs (horses) and handles pausing functionality. */ contract ERC721Facet is AccessControlInternal, ERC165BaseInternal, ERC721Base, ERC721Enumerable, ERC721Metadata, PartiallyPausableInternal, PausableInternal { using EnumerableSet for EnumerableSet.UintSet; event HorseMinted( MintMethod indexed method, uint256 indexed seasonId, uint256 indexed payoutTier, address to, uint256 tokenId ); /** * @dev Purchase horses by providing season, payout tier, and quantity. * @param _seasonId The ID of the season from which to purchase horses. * @param _payoutTier The ID of the payout tier for the purchase. * @param _quantity The quantity of horses to purchase. */ function purchase( uint256 _seasonId, uint256 _payoutTier, uint256 _quantity ) public payable whenNotPaused whenNotPartiallyPaused(HORSE_PURCHASING_PAUSED) { // Check if the sent Ether amount is valid PayoutTier storage payoutTier = LibSilksHorseDiamond.layout().payoutTiers[_payoutTier]; uint256 expectedEthTotal = payoutTier.price * _quantity; if (expectedEthTotal != msg.value){ revert InvalidIntValue( "INV_ETH_TOTAL", msg.value, expectedEthTotal ); } // Check if the purchase quantity is within the allowed limit per transaction if (payoutTier.maxPerTx != 0 && _quantity > payoutTier.maxPerTx){ revert InvalidIntValue( "PER_TX_ERROR", _quantity, payoutTier.maxPerTx ); } // Mint the specified quantity of horses to the sender _mintHorses(_seasonId, _payoutTier, _quantity, MintMethod.PURCHASE, msg.sender); } /** * @dev Airdrop horses by providing season, payout tier, quantity, and the recipient address. * @param _seasonId The ID of the season for the airdrop. * @param _payoutTier The ID of the payout tier for the airdrop. * @param _quantity The quantity of horses to airdrop. * @param _to The address to receive the airdropped horses. */ function airdrop( uint256 _seasonId, uint256 _payoutTier, uint256 _quantity, address _to ) public onlyRole(MINT_ADMIN_ROLE) { // Mint the specified quantity of horses and send them to the specified recipient _mintHorses(_seasonId, _payoutTier, _quantity, MintMethod.AIRDROP, _to); } /** * @dev Allows an external address to mint horses by providing season, payout tier, quantity, and the recipient address. * Checks if the calling address is in the allowed list of external mint addresses before minting. * @param _seasonId The ID of the season for the minted horses. * @param _payoutTier The ID of the payout tier for the minted horses. * @param _quantity The quantity of horses to mint. * @param _to The address to receive the minted horses. */ function externalMint( uint256 _seasonId, uint256 _payoutTier, uint256 _quantity, address _to ) external { // Check if the calling address is in the list of allowed external mint addresses bool inAllowedList = LibSilksHorseDiamond.layout().allowedExternalMintAddresses[msg.sender]; if (!inAllowedList){ revert InvalidExternalMintAddress( msg.sender ); } // Call the internal function to mint the horses _mintHorses(_seasonId, _payoutTier, _quantity, MintMethod.EXTERNAL_MINT, _to); } /** * @dev Mint horses based on season, payout tier, quantity, minting method, and recipient address. * @param _seasonId The ID of the season for minting horses. * @param _payoutTier The ID of the payout tier for minting horses. * @param _quantity The quantity of horses to mint. * @param _method The minting method used for the horses. * @param _to The address to receive the minted horses. * @dev This function is used to mint a specified quantity of horse tokens and associate them with a season and payout tier. * The minted horse tokens are then assigned to the provided recipient address. The function performs various checks * to ensure the specified season and payout tier are valid and not paused. It also checks for successful association of * horse tokens with the season and logs minting events. * @dev Emits a HorseMinted event upon successful minting. * @dev Reverts with specific error messages in case of invalid or paused season, invalid or paused payout tier, * failed association of tokens with the season, or any other minting failure. */ function _mintHorses( uint256 _seasonId, uint256 _payoutTier, uint256 _quantity, MintMethod _method, address _to ) private { // Check if the _quantity being minted will cause the maximum number of assets in wallet to be exceeded uint256 maxHorsesPerWallet = LibSilksHorseDiamond.layout().maxHorsesPerWallet; if (maxHorsesPerWallet > 0 &&( _balanceOf(_to) + _quantity) > maxHorsesPerWallet){ revert MaxHorsesPerWalletExceeded( _to ); } // Check if the specified season and payout tier are valid and not paused SeasonInfo storage seasonInfo = LibSilksHorseDiamond.layout().seasonInfos[_seasonId]; if (seasonInfo.paused || !seasonInfo.valid){ revert InvalidSeason( _seasonId ); } PayoutTier storage payoutTier = LibSilksHorseDiamond.layout().payoutTiers[_payoutTier]; if (payoutTier.paused || !payoutTier.valid){ revert InvalidPayoutTier( _payoutTier ); } LibSilksHorseDiamond.Layout storage lsh = LibSilksHorseDiamond.layout(); EnumerableSet.UintSet storage payoutTierHorses = lsh.payoutTierHorses[_payoutTier]; if (payoutTier.maxSupply > 0 && (payoutTierHorses.length() + _quantity) > payoutTier.maxSupply){ revert PayoutTierMaxSupplyExceeded( _payoutTier ); } EnumerableSet.UintSet storage seasonHorses = lsh.seasonHorses[_seasonId]; uint256 nextAvailableTokenId = lsh.nextAvailableTokenId; uint256 i = 0; // Mint the specified quantity of horses, associate them with the season, and set payout percentages for (; i < _quantity;) { uint256 _newTokenId = nextAvailableTokenId + i; if (!seasonHorses.add(_newTokenId)){ revert MintFailed( "TOKEN_CROP_ASSOCIATION_ERROR", _seasonId, _payoutTier, _quantity, _method, _to ); } if (!payoutTierHorses.add(_newTokenId)){ revert MintFailed( "TOKEN_PAYOUT_TIER_ASSOCIATION_ERROR", _seasonId, _payoutTier, _quantity, _method, _to ); } lsh.horsePayoutTier[_newTokenId] = payoutTier; lsh.horseSeasonInfo[_newTokenId] = seasonInfo; _safeMint(_to, _newTokenId); emit HorseMinted(_method, _seasonId, _payoutTier, _to, _newTokenId); unchecked { i++; } } lsh.nextAvailableTokenId = nextAvailableTokenId + i; } /** * @dev Hook function called before token transfer, inherited from ERC721Metadata. * @param from The sender of the tokens. * @param to The recipient of the tokens. * @param tokenId The ID of the token being transferred. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override( ERC721Metadata, ERC721BaseInternal ) { super._beforeTokenTransfer(from, to, tokenId); } /** * @notice query whether contract has registered support for given interface * @param interfaceId interface id * @return bool whether interface is supported */ function supportsInterface( bytes4 interfaceId ) external view returns ( bool ) { return super._supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { EnumerableSet } from '../../data/EnumerableSet.sol'; import { AddressUtils } from '../../utils/AddressUtils.sol'; import { UintUtils } from '../../utils/UintUtils.sol'; import { IAccessControlInternal } from './IAccessControlInternal.sol'; import { AccessControlStorage } from './AccessControlStorage.sol'; /** * @title Role-based access control system * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ abstract contract AccessControlInternal is IAccessControlInternal { using AddressUtils for address; using EnumerableSet for EnumerableSet.AddressSet; using UintUtils for uint256; modifier onlyRole(bytes32 role) { _checkRole(role); _; } /* * @notice query whether role is assigned to account * @param role role to query * @param account account to query * @return whether role is assigned to account */ function _hasRole( bytes32 role, address account ) internal view virtual returns (bool) { return AccessControlStorage.layout().roles[role].members.contains(account); } /** * @notice revert if sender does not have given role * @param role role to query */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, msg.sender); } /** * @notice revert if given account does not have given role * @param role role to query * @param account to query */ function _checkRole(bytes32 role, address account) internal view virtual { if (!_hasRole(role, account)) { revert( string( abi.encodePacked( 'AccessControl: account ', account.toString(), ' is missing role ', uint256(role).toHexString(32) ) ) ); } } /* * @notice query admin role for given role * @param role role to query * @return admin role */ function _getRoleAdmin( bytes32 role ) internal view virtual returns (bytes32) { return AccessControlStorage.layout().roles[role].adminRole; } /** * @notice set role as admin role * @param role role to set * @param adminRole admin role to set */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = _getRoleAdmin(role); AccessControlStorage.layout().roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /* * @notice assign role to given account * @param role role to assign * @param account recipient of role assignment */ function _grantRole(bytes32 role, address account) internal virtual { AccessControlStorage.layout().roles[role].members.add(account); emit RoleGranted(role, account, msg.sender); } /* * @notice unassign role from given account * @param role role to unassign * @parm account */ function _revokeRole(bytes32 role, address account) internal virtual { AccessControlStorage.layout().roles[role].members.remove(account); emit RoleRevoked(role, account, msg.sender); } /** * @notice relinquish role * @param role role to relinquish */ function _renounceRole(bytes32 role) internal virtual { _revokeRole(role, msg.sender); } /** * @notice query role for member at given index * @param role role to query * @param index index to query */ function _getRoleMember( bytes32 role, uint256 index ) internal view virtual returns (address) { return AccessControlStorage.layout().roles[role].members.at(index); } /** * @notice query role for member count * @param role role to query */ function _getRoleMemberCount( bytes32 role ) internal view virtual returns (uint256) { return AccessControlStorage.layout().roles[role].members.length(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { EnumerableSet } from '../../data/EnumerableSet.sol'; library AccessControlStorage { struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; } struct Layout { mapping(bytes32 => RoleData) roles; } bytes32 internal constant DEFAULT_ADMIN_ROLE = 0x00; bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.AccessControl'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Partial AccessControl interface needed by internal functions */ interface IAccessControlInternal { event RoleAdminChanged( bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole ); event RoleGranted( bytes32 indexed role, address indexed account, address indexed sender ); event RoleRevoked( bytes32 indexed role, address indexed account, address indexed sender ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Map implementation with enumeration functions * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ library EnumerableMap { error EnumerableMap__IndexOutOfBounds(); error EnumerableMap__NonExistentKey(); struct MapEntry { bytes32 _key; bytes32 _value; } struct Map { MapEntry[] _entries; // 1-indexed to allow 0 to signify nonexistence mapping(bytes32 => uint256) _indexes; } struct AddressToAddressMap { Map _inner; } struct UintToAddressMap { Map _inner; } function at( AddressToAddressMap storage map, uint256 index ) internal view returns (address, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return ( address(uint160(uint256(key))), address(uint160(uint256(value))) ); } function at( UintToAddressMap storage map, uint256 index ) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } function contains( AddressToAddressMap storage map, address key ) internal view returns (bool) { return _contains(map._inner, bytes32(uint256(uint160(key)))); } function contains( UintToAddressMap storage map, uint256 key ) internal view returns (bool) { return _contains(map._inner, bytes32(key)); } function length( AddressToAddressMap storage map ) internal view returns (uint256) { return _length(map._inner); } function length( UintToAddressMap storage map ) internal view returns (uint256) { return _length(map._inner); } function get( AddressToAddressMap storage map, address key ) internal view returns (address) { return address( uint160( uint256(_get(map._inner, bytes32(uint256(uint160(key))))) ) ); } function get( UintToAddressMap storage map, uint256 key ) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(key))))); } function set( AddressToAddressMap storage map, address key, address value ) internal returns (bool) { return _set( map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value))) ); } function set( UintToAddressMap storage map, uint256 key, address value ) internal returns (bool) { return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } function remove( AddressToAddressMap storage map, address key ) internal returns (bool) { return _remove(map._inner, bytes32(uint256(uint160(key)))); } function remove( UintToAddressMap storage map, uint256 key ) internal returns (bool) { return _remove(map._inner, bytes32(key)); } function toArray( AddressToAddressMap storage map ) internal view returns (address[] memory keysOut, address[] memory valuesOut) { uint256 len = map._inner._entries.length; keysOut = new address[](len); valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = address( uint160(uint256(map._inner._entries[i]._key)) ); valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function toArray( UintToAddressMap storage map ) internal view returns (uint256[] memory keysOut, address[] memory valuesOut) { uint256 len = map._inner._entries.length; keysOut = new uint256[](len); valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = uint256(map._inner._entries[i]._key); valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function keys( AddressToAddressMap storage map ) internal view returns (address[] memory keysOut) { uint256 len = map._inner._entries.length; keysOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = address( uint160(uint256(map._inner._entries[i]._key)) ); } } } function keys( UintToAddressMap storage map ) internal view returns (uint256[] memory keysOut) { uint256 len = map._inner._entries.length; keysOut = new uint256[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = uint256(map._inner._entries[i]._key); } } } function values( AddressToAddressMap storage map ) internal view returns (address[] memory valuesOut) { uint256 len = map._inner._entries.length; valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function values( UintToAddressMap storage map ) internal view returns (address[] memory valuesOut) { uint256 len = map._inner._entries.length; valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function _at( Map storage map, uint256 index ) private view returns (bytes32, bytes32) { if (index >= map._entries.length) revert EnumerableMap__IndexOutOfBounds(); MapEntry storage entry = map._entries[index]; return (entry._key, entry._value); } function _contains( Map storage map, bytes32 key ) private view returns (bool) { return map._indexes[key] != 0; } function _length(Map storage map) private view returns (uint256) { return map._entries.length; } function _get(Map storage map, bytes32 key) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) revert EnumerableMap__NonExistentKey(); unchecked { return map._entries[keyIndex - 1]._value; } } function _set( Map storage map, bytes32 key, bytes32 value ) private returns (bool) { uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) { map._entries.push(MapEntry({ _key: key, _value: value })); map._indexes[key] = map._entries.length; return true; } else { unchecked { map._entries[keyIndex - 1]._value = value; } return false; } } function _remove(Map storage map, bytes32 key) private returns (bool) { uint256 keyIndex = map._indexes[key]; if (keyIndex != 0) { unchecked { MapEntry storage last = map._entries[map._entries.length - 1]; // move last entry to now-vacant index map._entries[keyIndex - 1] = last; map._indexes[last._key] = keyIndex; } // clear last index map._entries.pop(); delete map._indexes[key]; return true; } else { return false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Set implementation with enumeration functions * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ library EnumerableSet { error EnumerableSet__IndexOutOfBounds(); struct Set { bytes32[] _values; // 1-indexed to allow 0 to signify nonexistence mapping(bytes32 => uint256) _indexes; } struct Bytes32Set { Set _inner; } struct AddressSet { Set _inner; } struct UintSet { Set _inner; } function at( Bytes32Set storage set, uint256 index ) internal view returns (bytes32) { return _at(set._inner, index); } function at( AddressSet storage set, uint256 index ) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } function at( UintSet storage set, uint256 index ) internal view returns (uint256) { return uint256(_at(set._inner, index)); } function contains( Bytes32Set storage set, bytes32 value ) internal view returns (bool) { return _contains(set._inner, value); } function contains( AddressSet storage set, address value ) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } function contains( UintSet storage set, uint256 value ) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } function indexOf( Bytes32Set storage set, bytes32 value ) internal view returns (uint256) { return _indexOf(set._inner, value); } function indexOf( AddressSet storage set, address value ) internal view returns (uint256) { return _indexOf(set._inner, bytes32(uint256(uint160(value)))); } function indexOf( UintSet storage set, uint256 value ) internal view returns (uint256) { return _indexOf(set._inner, bytes32(value)); } function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } function add( Bytes32Set storage set, bytes32 value ) internal returns (bool) { return _add(set._inner, value); } function add( AddressSet storage set, address value ) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } function remove( Bytes32Set storage set, bytes32 value ) internal returns (bool) { return _remove(set._inner, value); } function remove( AddressSet storage set, address value ) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } function remove( UintSet storage set, uint256 value ) internal returns (bool) { return _remove(set._inner, bytes32(value)); } function toArray( Bytes32Set storage set ) internal view returns (bytes32[] memory) { return set._inner._values; } function toArray( AddressSet storage set ) internal view returns (address[] memory) { bytes32[] storage values = set._inner._values; address[] storage array; assembly { array.slot := values.slot } return array; } function toArray( UintSet storage set ) internal view returns (uint256[] memory) { bytes32[] storage values = set._inner._values; uint256[] storage array; assembly { array.slot := values.slot } return array; } function _at( Set storage set, uint256 index ) private view returns (bytes32) { if (index >= set._values.length) revert EnumerableSet__IndexOutOfBounds(); return set._values[index]; } function _contains( Set storage set, bytes32 value ) private view returns (bool) { return set._indexes[value] != 0; } function _indexOf( Set storage set, bytes32 value ) private view returns (uint256) { unchecked { return set._indexes[value] - 1; } } function _length(Set storage set) private view returns (uint256) { return set._values.length; } function _add( Set storage set, bytes32 value ) private returns (bool status) { if (!_contains(set, value)) { set._values.push(value); set._indexes[value] = set._values.length; status = true; } } function _remove( Set storage set, bytes32 value ) private returns (bool status) { uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { unchecked { bytes32 last = set._values[set._values.length - 1]; // move last value to now-vacant index set._values[valueIndex - 1] = last; set._indexes[last] = valueIndex; } // clear last index set._values.pop(); delete set._indexes[value]; status = true; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC165Internal } from './IERC165Internal.sol'; /** * @title ERC165 interface registration interface * @dev see https://eips.ethereum.org/EIPS/eip-165 */ interface IERC165 is IERC165Internal { /** * @notice query whether contract has registered support for given interface * @param interfaceId interface id * @return bool whether interface is supported */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title ERC165 interface registration interface */ interface IERC165Internal { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC165 } from './IERC165.sol'; import { IERC721Internal } from './IERC721Internal.sol'; /** * @title ERC721 interface * @dev see https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721 is IERC721Internal, IERC165 { /** * @notice query the balance of given address * @return balance quantity of tokens held */ function balanceOf(address account) external view returns (uint256 balance); /** * @notice query the owner of given token * @param tokenId token to query * @return owner token owner */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable * @param from sender of token * @param to receiver of token * @param tokenId token id */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable * @param from sender of token * @param to receiver of token * @param tokenId token id * @param data data payload */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @notice transfer token between given addresses, without checking for ERC721Receiver implementation if applicable * @param from sender of token * @param to receiver of token * @param tokenId token id */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @notice grant approval to given account to spend token * @param operator address to be approved * @param tokenId token to approve */ function approve(address operator, uint256 tokenId) external payable; /** * @notice get approval status for given token * @param tokenId token to query * @return operator address approved to spend token */ function getApproved( uint256 tokenId ) external view returns (address operator); /** * @notice grant approval to or revoke approval from given account to spend all tokens held by sender * @param operator address to be approved * @param status approval status */ function setApprovalForAll(address operator, bool status) external; /** * @notice query approval status of given operator with respect to given address * @param account address to query for approval granted * @param operator address to query for approval received * @return status whether operator is approved to spend tokens held by account */ function isApprovedForAll( address account, address operator ) external view returns (bool status); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Partial ERC721 interface needed by internal functions */ interface IERC721Internal { event Transfer( address indexed from, address indexed to, uint256 indexed tokenId ); event Approval( address indexed owner, address indexed operator, uint256 indexed tokenId ); event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; interface IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC165BaseInternal } from './IERC165BaseInternal.sol'; import { ERC165BaseStorage } from './ERC165BaseStorage.sol'; /** * @title ERC165 implementation */ abstract contract ERC165BaseInternal is IERC165BaseInternal { /** * @notice indicates whether an interface is already supported based on the interfaceId * @param interfaceId id of interface to check * @return bool indicating whether interface is supported */ function _supportsInterface( bytes4 interfaceId ) internal view virtual returns (bool) { return ERC165BaseStorage.layout().supportedInterfaces[interfaceId]; } /** * @notice sets status of interface support * @param interfaceId id of interface to set status for * @param status boolean indicating whether interface will be set as supported */ function _setSupportsInterface( bytes4 interfaceId, bool status ) internal virtual { if (interfaceId == 0xffffffff) revert ERC165Base__InvalidInterfaceId(); ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library ERC165BaseStorage { struct Layout { mapping(bytes4 => bool) supportedInterfaces; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ERC165Base'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC165Internal } from '../../../interfaces/IERC165Internal.sol'; interface IERC165BaseInternal is IERC165Internal { error ERC165Base__InvalidInterfaceId(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; interface IPartiallyPausableInternal { error PartiallyPausable__PartiallyPaused(); error PartiallyPausable__NotPartiallyPaused(); event PartiallyPaused(address account, bytes32 key); event PartiallyUnpaused(address account, bytes32 key); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IPartiallyPausableInternal } from './IPartiallyPausableInternal.sol'; import { PartiallyPausableStorage } from './PartiallyPausableStorage.sol'; /** * @title Internal functions for PartiallyPausable security control module. */ abstract contract PartiallyPausableInternal is IPartiallyPausableInternal { modifier whenNotPartiallyPaused(bytes32 key) { if (_partiallyPaused(key)) revert PartiallyPausable__PartiallyPaused(); _; } modifier whenPartiallyPaused(bytes32 key) { if (!_partiallyPaused(key)) revert PartiallyPausable__NotPartiallyPaused(); _; } /** * @notice query whether contract is paused in the scope of the given key * @return status whether contract is paused in the scope of the given key */ function _partiallyPaused( bytes32 key ) internal view virtual returns (bool status) { status = PartiallyPausableStorage.layout().partiallyPaused[key]; } /** * @notice pause contract in the scope of given key * @param key key whose scope to pause */ function _partiallyPause( bytes32 key ) internal virtual whenNotPartiallyPaused(key) { PartiallyPausableStorage.layout().partiallyPaused[key] = true; emit PartiallyPaused(msg.sender, key); } /** * @notice unpause contract in the scope of given key * @param key key whose scope to unpause */ function _partiallyUnpause( bytes32 key ) internal virtual whenPartiallyPaused(key) { delete PartiallyPausableStorage.layout().partiallyPaused[key]; emit PartiallyUnpaused(msg.sender, key); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library PartiallyPausableStorage { struct Layout { mapping(bytes32 => bool) partiallyPaused; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.PartiallyPausable'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; interface IPausableInternal { error Pausable__Paused(); error Pausable__NotPaused(); event Paused(address account); event Unpaused(address account); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IPausableInternal } from './IPausableInternal.sol'; import { PausableStorage } from './PausableStorage.sol'; /** * @title Internal functions for Pausable security control module. */ abstract contract PausableInternal is IPausableInternal { modifier whenNotPaused() { if (_paused()) revert Pausable__Paused(); _; } modifier whenPaused() { if (!_paused()) revert Pausable__NotPaused(); _; } /** * @notice query whether contract is paused * @return status whether contract is paused */ function _paused() internal view virtual returns (bool status) { status = PausableStorage.layout().paused; } /** * @notice Triggers paused state, when contract is unpaused. */ function _pause() internal virtual whenNotPaused { PausableStorage.layout().paused = true; emit Paused(msg.sender); } /** * @notice Triggers unpaused state, when contract is paused. */ function _unpause() internal virtual whenPaused { delete PausableStorage.layout().paused; emit Unpaused(msg.sender); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library PausableStorage { struct Layout { bool paused; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.Pausable'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721 } from '../../../interfaces/IERC721.sol'; import { IERC721Base } from './IERC721Base.sol'; import { ERC721BaseInternal } from './ERC721BaseInternal.sol'; /** * @title Base ERC721 implementation, excluding optional extensions * @dev inheritor must either implement ERC165 supportsInterface or inherit ERC165Base */ abstract contract ERC721Base is IERC721Base, ERC721BaseInternal { /** * @inheritdoc IERC721 */ function balanceOf(address account) external view returns (uint256) { return _balanceOf(account); } /** * @inheritdoc IERC721 */ function ownerOf(uint256 tokenId) external view returns (address) { return _ownerOf(tokenId); } /** * @inheritdoc IERC721 */ function getApproved(uint256 tokenId) external view returns (address) { return _getApproved(tokenId); } /** * @inheritdoc IERC721 */ function isApprovedForAll( address account, address operator ) external view returns (bool) { return _isApprovedForAll(account, operator); } /** * @inheritdoc IERC721 */ function transferFrom( address from, address to, uint256 tokenId ) external payable { _transferFrom(from, to, tokenId); } /** * @inheritdoc IERC721 */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable { _safeTransferFrom(from, to, tokenId); } /** * @inheritdoc IERC721 */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) external payable { _safeTransferFrom(from, to, tokenId, data); } /** * @inheritdoc IERC721 */ function approve(address operator, uint256 tokenId) external payable { _approve(operator, tokenId); } /** * @inheritdoc IERC721 */ function setApprovalForAll(address operator, bool status) external { _setApprovalForAll(operator, status); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721Receiver } from '../../../interfaces/IERC721Receiver.sol'; import { EnumerableMap } from '../../../data/EnumerableMap.sol'; import { EnumerableSet } from '../../../data/EnumerableSet.sol'; import { AddressUtils } from '../../../utils/AddressUtils.sol'; import { IERC721BaseInternal } from './IERC721BaseInternal.sol'; import { ERC721BaseStorage } from './ERC721BaseStorage.sol'; /** * @title Base ERC721 internal functions */ abstract contract ERC721BaseInternal is IERC721BaseInternal { using AddressUtils for address; using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.UintSet; function _balanceOf( address account ) internal view virtual returns (uint256) { if (account == address(0)) revert ERC721Base__BalanceQueryZeroAddress(); return ERC721BaseStorage.layout().holderTokens[account].length(); } function _ownerOf(uint256 tokenId) internal view virtual returns (address) { address owner = ERC721BaseStorage.layout().tokenOwners.get(tokenId); if (owner == address(0)) revert ERC721Base__InvalidOwner(); return owner; } function _exists(uint256 tokenId) internal view virtual returns (bool) { return ERC721BaseStorage.layout().tokenOwners.contains(tokenId); } function _getApproved( uint256 tokenId ) internal view virtual returns (address) { if (!_exists(tokenId)) revert ERC721Base__NonExistentToken(); return ERC721BaseStorage.layout().tokenApprovals[tokenId]; } function _isApprovedForAll( address account, address operator ) internal view virtual returns (bool) { return ERC721BaseStorage.layout().operatorApprovals[account][operator]; } function _isApprovedOrOwner( address spender, uint256 tokenId ) internal view virtual returns (bool) { if (!_exists(tokenId)) revert ERC721Base__NonExistentToken(); address owner = _ownerOf(tokenId); return (spender == owner || _getApproved(tokenId) == spender || _isApprovedForAll(owner, spender)); } function _mint(address to, uint256 tokenId) internal virtual { if (to == address(0)) revert ERC721Base__MintToZeroAddress(); if (_exists(tokenId)) revert ERC721Base__TokenAlreadyMinted(); _beforeTokenTransfer(address(0), to, tokenId); ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); l.holderTokens[to].add(tokenId); l.tokenOwners.set(tokenId, to); emit Transfer(address(0), to, tokenId); } function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ''); } function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); if (!_checkOnERC721Received(address(0), to, tokenId, data)) revert ERC721Base__ERC721ReceiverNotImplemented(); } function _burn(uint256 tokenId) internal virtual { address owner = _ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); l.holderTokens[owner].remove(tokenId); l.tokenOwners.remove(tokenId); l.tokenApprovals[tokenId] = address(0); emit Approval(owner, address(0), tokenId); emit Transfer(owner, address(0), tokenId); } function _transfer( address from, address to, uint256 tokenId ) internal virtual { address owner = _ownerOf(tokenId); if (owner != from) revert ERC721Base__NotTokenOwner(); if (to == address(0)) revert ERC721Base__TransferToZeroAddress(); _beforeTokenTransfer(from, to, tokenId); ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); l.holderTokens[from].remove(tokenId); l.holderTokens[to].add(tokenId); l.tokenOwners.set(tokenId, to); l.tokenApprovals[tokenId] = address(0); emit Approval(owner, address(0), tokenId); emit Transfer(from, to, tokenId); } function _transferFrom( address from, address to, uint256 tokenId ) internal virtual { _handleTransferMessageValue(from, to, tokenId, msg.value); if (!_isApprovedOrOwner(msg.sender, tokenId)) revert ERC721Base__NotOwnerOrApproved(); _transfer(from, to, tokenId); } function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); if (!_checkOnERC721Received(from, to, tokenId, data)) revert ERC721Base__ERC721ReceiverNotImplemented(); } function _safeTransferFrom( address from, address to, uint256 tokenId ) internal virtual { _safeTransferFrom(from, to, tokenId, ''); } function _safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _handleTransferMessageValue(from, to, tokenId, msg.value); if (!_isApprovedOrOwner(msg.sender, tokenId)) revert ERC721Base__NotOwnerOrApproved(); _safeTransfer(from, to, tokenId, data); } function _approve(address operator, uint256 tokenId) internal virtual { _handleApproveMessageValue(operator, tokenId, msg.value); address owner = _ownerOf(tokenId); if (operator == owner) revert ERC721Base__SelfApproval(); if (msg.sender != owner && !_isApprovedForAll(owner, msg.sender)) revert ERC721Base__NotOwnerOrApproved(); ERC721BaseStorage.layout().tokenApprovals[tokenId] = operator; emit Approval(owner, operator, tokenId); } function _setApprovalForAll( address operator, bool status ) internal virtual { if (operator == msg.sender) revert ERC721Base__SelfApproval(); ERC721BaseStorage.layout().operatorApprovals[msg.sender][ operator ] = status; emit ApprovalForAll(msg.sender, operator, status); } function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) internal virtual returns (bool) { if (!to.isContract()) { return true; } bytes memory returnData = to.functionCall( abi.encodeWithSelector( IERC721Receiver(to).onERC721Received.selector, msg.sender, from, tokenId, data ), 'ERC721: transfer to non ERC721Receiver implementer' ); bytes4 returnValue = abi.decode(returnData, (bytes4)); return returnValue == type(IERC721Receiver).interfaceId; } /** * @notice ERC721 hook, called before externally called approvals for processing of included message value * @param operator beneficiary of approval * @param tokenId id of transferred token * @param value message value */ function _handleApproveMessageValue( address operator, uint256 tokenId, uint256 value ) internal virtual {} /** * @notice ERC721 hook, called before externally called transfers for processing of included message value * @param from sender of token * @param to receiver of token * @param tokenId id of transferred token * @param value message value */ function _handleTransferMessageValue( address from, address to, uint256 tokenId, uint256 value ) internal virtual {} /** * @notice ERC721 hook, called before all transfers including mint and burn * @dev function should be overridden and new implementation must call super * @param from sender of token * @param to receiver of token * @param tokenId id of transferred token */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { EnumerableMap } from '../../../data/EnumerableMap.sol'; import { EnumerableSet } from '../../../data/EnumerableSet.sol'; library ERC721BaseStorage { using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ERC721Base'); struct Layout { EnumerableMap.UintToAddressMap tokenOwners; mapping(address => EnumerableSet.UintSet) holderTokens; mapping(uint256 => address) tokenApprovals; mapping(address => mapping(address => bool)) operatorApprovals; } function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721 } from '../../../interfaces/IERC721.sol'; import { IERC721BaseInternal } from './IERC721BaseInternal.sol'; /** * @title ERC721 base interface */ interface IERC721Base is IERC721BaseInternal, IERC721 { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721Internal } from '../../../interfaces/IERC721Internal.sol'; /** * @title ERC721 base interface */ interface IERC721BaseInternal is IERC721Internal { error ERC721Base__NotOwnerOrApproved(); error ERC721Base__SelfApproval(); error ERC721Base__BalanceQueryZeroAddress(); error ERC721Base__ERC721ReceiverNotImplemented(); error ERC721Base__InvalidOwner(); error ERC721Base__MintToZeroAddress(); error ERC721Base__NonExistentToken(); error ERC721Base__NotTokenOwner(); error ERC721Base__TokenAlreadyMinted(); error ERC721Base__TransferToZeroAddress(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { EnumerableMap } from '../../../data/EnumerableMap.sol'; import { EnumerableSet } from '../../../data/EnumerableSet.sol'; import { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol'; import { IERC721Enumerable } from './IERC721Enumerable.sol'; import { ERC721EnumerableInternal } from './ERC721EnumerableInternal.sol'; abstract contract ERC721Enumerable is IERC721Enumerable, ERC721EnumerableInternal { using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.UintSet; /** * @inheritdoc IERC721Enumerable */ function totalSupply() public view returns (uint256) { return _totalSupply(); } /** * @inheritdoc IERC721Enumerable */ function tokenOfOwnerByIndex( address owner, uint256 index ) public view returns (uint256) { return _tokenOfOwnerByIndex(owner, index); } /** * @inheritdoc IERC721Enumerable */ function tokenByIndex(uint256 index) public view returns (uint256) { return _tokenByIndex(index); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { EnumerableMap } from '../../../data/EnumerableMap.sol'; import { EnumerableSet } from '../../../data/EnumerableSet.sol'; import { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol'; abstract contract ERC721EnumerableInternal { using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.UintSet; /** * @notice TODO */ function _totalSupply() internal view returns (uint256) { return ERC721BaseStorage.layout().tokenOwners.length(); } /** * @notice TODO */ function _tokenOfOwnerByIndex( address owner, uint256 index ) internal view returns (uint256) { return ERC721BaseStorage.layout().holderTokens[owner].at(index); } /** * @notice TODO */ function _tokenByIndex( uint256 index ) internal view returns (uint256 tokenId) { (tokenId, ) = ERC721BaseStorage.layout().tokenOwners.at(index); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; interface IERC721Enumerable { /** * @notice get total token supply * @return total supply */ function totalSupply() external view returns (uint256); /** * @notice get token of given owner at given internal storage index * @param owner token holder to query * @param index position in owner's token list to query * @return tokenId id of retrieved token */ function tokenOfOwnerByIndex( address owner, uint256 index ) external view returns (uint256 tokenId); /** * @notice get token at given internal storage index * @param index position in global token list to query * @return tokenId id of retrieved token */ function tokenByIndex( uint256 index ) external view returns (uint256 tokenId); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { ERC721MetadataInternal } from './ERC721MetadataInternal.sol'; import { IERC721Metadata } from './IERC721Metadata.sol'; /** * @title ERC721 metadata extensions */ abstract contract ERC721Metadata is IERC721Metadata, ERC721MetadataInternal { /** * @notice inheritdoc IERC721Metadata */ function name() external view virtual returns (string memory) { return _name(); } /** * @notice inheritdoc IERC721Metadata */ function symbol() external view virtual returns (string memory) { return _symbol(); } /** * @notice inheritdoc IERC721Metadata */ function tokenURI( uint256 tokenId ) external view virtual returns (string memory) { return _tokenURI(tokenId); } /** * @inheritdoc ERC721MetadataInternal */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { UintUtils } from '../../../utils/UintUtils.sol'; import { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol'; import { ERC721BaseInternal } from '../base/ERC721Base.sol'; import { IERC721MetadataInternal } from './IERC721MetadataInternal.sol'; import { ERC721MetadataStorage } from './ERC721MetadataStorage.sol'; /** * @title ERC721Metadata internal functions */ abstract contract ERC721MetadataInternal is IERC721MetadataInternal, ERC721BaseInternal { using UintUtils for uint256; /** * @notice get token name * @return token name */ function _name() internal view virtual returns (string memory) { return ERC721MetadataStorage.layout().name; } /** * @notice get token symbol * @return token symbol */ function _symbol() internal view virtual returns (string memory) { return ERC721MetadataStorage.layout().symbol; } /** * @notice get generated URI for given token * @return token URI */ function _tokenURI( uint256 tokenId ) internal view virtual returns (string memory) { if (!_exists(tokenId)) revert ERC721Metadata__NonExistentToken(); ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout(); string memory tokenIdURI = l.tokenURIs[tokenId]; string memory baseURI = l.baseURI; if (bytes(baseURI).length == 0) { return tokenIdURI; } else if (bytes(tokenIdURI).length > 0) { return string(abi.encodePacked(baseURI, tokenIdURI)); } else { return string(abi.encodePacked(baseURI, tokenId.toString())); } } /** * @notice ERC721 hook: clear per-token URI data on burn * @inheritdoc ERC721BaseInternal */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (to == address(0)) { delete ERC721MetadataStorage.layout().tokenURIs[tokenId]; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library ERC721MetadataStorage { bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ERC721Metadata'); struct Layout { string name; string symbol; string baseURI; mapping(uint256 => string) tokenURIs; } function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721MetadataInternal } from './IERC721MetadataInternal.sol'; /** * @title ERC721Metadata interface */ interface IERC721Metadata is IERC721MetadataInternal { /** * @notice get token name * @return token name */ function name() external view returns (string memory); /** * @notice get token symbol * @return token symbol */ function symbol() external view returns (string memory); /** * @notice get generated URI for given token * @return token URI */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721BaseInternal } from '../base/IERC721BaseInternal.sol'; /** * @title ERC721Metadata internal interface */ interface IERC721MetadataInternal is IERC721BaseInternal { error ERC721Metadata__NonExistentToken(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { UintUtils } from './UintUtils.sol'; library AddressUtils { using UintUtils for uint256; error AddressUtils__InsufficientBalance(); error AddressUtils__NotContract(); error AddressUtils__SendValueFailed(); function toString(address account) internal pure returns (string memory) { return uint256(uint160(account)).toHexString(20); } function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } function sendValue(address payable account, uint256 amount) internal { (bool success, ) = account.call{ value: amount }(''); if (!success) revert AddressUtils__SendValueFailed(); } function functionCall( address target, bytes memory data ) internal returns (bytes memory) { return functionCall(target, data, 'AddressUtils: failed low-level call'); } function functionCall( address target, bytes memory data, string memory error ) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, error); } function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, 'AddressUtils: failed low-level call with value' ); } function functionCallWithValue( address target, bytes memory data, uint256 value, string memory error ) internal returns (bytes memory) { if (value > address(this).balance) revert AddressUtils__InsufficientBalance(); return _functionCallWithValue(target, data, value, error); } /** * @notice execute arbitrary external call with limited gas usage and amount of copied return data * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License) * @param target recipient of call * @param gasAmount gas allowance for call * @param value native token value to include in call * @param maxCopy maximum number of bytes to copy from return data * @param data encoded call data * @return success whether call is successful * @return returnData copied return data */ function excessivelySafeCall( address target, uint256 gasAmount, uint256 value, uint16 maxCopy, bytes memory data ) internal returns (bool success, bytes memory returnData) { returnData = new bytes(maxCopy); assembly { // execute external call via assembly to avoid automatic copying of return data success := call( gasAmount, target, value, add(data, 0x20), mload(data), 0, 0 ) // determine whether to limit amount of data to copy let toCopy := returndatasize() if gt(toCopy, maxCopy) { toCopy := maxCopy } // store the length of the copied bytes mstore(returnData, toCopy) // copy the bytes from returndata[0:toCopy] returndatacopy(add(returnData, 0x20), 0, toCopy) } } function _functionCallWithValue( address target, bytes memory data, uint256 value, string memory error ) private returns (bytes memory) { if (!isContract(target)) revert AddressUtils__NotContract(); (bool success, bytes memory returnData) = target.call{ value: value }( data ); if (success) { return returnData; } else if (returnData.length > 0) { assembly { let returnData_size := mload(returnData) revert(add(32, returnData), returnData_size) } } else { revert(error); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title utility functions for uint256 operations * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license) */ library UintUtils { error UintUtils__InsufficientHexLength(); bytes16 private constant HEX_SYMBOLS = '0123456789abcdef'; function add(uint256 a, int256 b) internal pure returns (uint256) { return b < 0 ? sub(a, -b) : a + uint256(b); } function sub(uint256 a, int256 b) internal pure returns (uint256) { return b < 0 ? add(a, -b) : a - uint256(b); } function toString(uint256 value) internal pure returns (string memory) { if (value == 0) { return '0'; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return '0x00'; } uint256 length = 0; for (uint256 temp = value; temp != 0; temp >>= 8) { unchecked { length++; } } return toHexString(value, length); } function toHexString( uint256 value, uint256 length ) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = '0'; buffer[1] = 'x'; unchecked { for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_SYMBOLS[value & 0xf]; value >>= 4; } } if (value != 0) revert UintUtils__InsufficientHexLength(); return string(buffer); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; import {EnumerableSet} from "@solidstate/contracts/data/EnumerableSet.sol"; struct SeasonInfo { uint256 seasonId; string description; bool paused; bool valid; } struct PayoutTier { uint256 tierId; string description; uint256 price; uint256 maxPerTx; uint256 payoutPct; uint256 maxSupply; bool paused; bool valid; } enum MintMethod { PURCHASE, AIRDROP, EXTERNAL_MINT } bytes32 constant CONTRACT_ADMIN_ROLE = keccak256("silks.contracts.roles.ContractAdminRole"); bytes32 constant MINT_ADMIN_ROLE = keccak256("silks.contracts.roles.MintAdminRole"); bytes32 constant HORSE_PURCHASING_PAUSED = keccak256('silks.contracts.paused.HorsePurchasing'); error InvalidAddress(address _address); error InvalidSeason(uint256 _sent); error InvalidPayoutTier(uint256 _sent); error InvalidTokenId(uint256 _sent); error InvalidIntValue(string _reason, uint256 _sent, uint256 _expected); error InvalidStringValue(string _reason, string _sent, string _expected); error InvalidExternalMintAddress(address _sender); error MaxHorsesPerWalletExceeded(address _walletAddress); error PayoutTierMaxSupplyExceeded(uint256 _payoutTier); error MintFailed(string _reason, uint256 _seasonId, uint256 _payoutTier, uint256 _quantity, MintMethod _method, address _to); library LibSilksHorseDiamond { bytes32 internal constant STORAGE_SLOT = keccak256('silks.contracts.storage.SilksHorseDiamond'); struct Layout { mapping(uint256 => EnumerableSet.UintSet) seasonHorses; mapping(uint256 => SeasonInfo) seasonInfos; mapping(uint256 => PayoutTier) payoutTiers; mapping(uint256 => PayoutTier) horsePayoutTier; mapping(uint256 => EnumerableSet.UintSet) payoutTierHorses; mapping(uint256 => SeasonInfo) horseSeasonInfo; mapping(address => bool) allowedExternalMintAddresses; uint256 maxHorsesPerWallet; uint256 nextAvailableTokenId; } function layout() internal pure returns ( Layout storage l ) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AddressUtils__NotContract","type":"error"},{"inputs":[],"name":"ERC165Base__InvalidInterfaceId","type":"error"},{"inputs":[],"name":"ERC721Base__BalanceQueryZeroAddress","type":"error"},{"inputs":[],"name":"ERC721Base__ERC721ReceiverNotImplemented","type":"error"},{"inputs":[],"name":"ERC721Base__InvalidOwner","type":"error"},{"inputs":[],"name":"ERC721Base__MintToZeroAddress","type":"error"},{"inputs":[],"name":"ERC721Base__NonExistentToken","type":"error"},{"inputs":[],"name":"ERC721Base__NotOwnerOrApproved","type":"error"},{"inputs":[],"name":"ERC721Base__NotTokenOwner","type":"error"},{"inputs":[],"name":"ERC721Base__SelfApproval","type":"error"},{"inputs":[],"name":"ERC721Base__TokenAlreadyMinted","type":"error"},{"inputs":[],"name":"ERC721Base__TransferToZeroAddress","type":"error"},{"inputs":[],"name":"ERC721Metadata__NonExistentToken","type":"error"},{"inputs":[],"name":"EnumerableMap__IndexOutOfBounds","type":"error"},{"inputs":[],"name":"EnumerableMap__NonExistentKey","type":"error"},{"inputs":[],"name":"EnumerableSet__IndexOutOfBounds","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"InvalidExternalMintAddress","type":"error"},{"inputs":[{"internalType":"string","name":"_reason","type":"string"},{"internalType":"uint256","name":"_sent","type":"uint256"},{"internalType":"uint256","name":"_expected","type":"uint256"}],"name":"InvalidIntValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"_sent","type":"uint256"}],"name":"InvalidPayoutTier","type":"error"},{"inputs":[{"internalType":"uint256","name":"_sent","type":"uint256"}],"name":"InvalidSeason","type":"error"},{"inputs":[{"internalType":"address","name":"_walletAddress","type":"address"}],"name":"MaxHorsesPerWalletExceeded","type":"error"},{"inputs":[{"internalType":"string","name":"_reason","type":"string"},{"internalType":"uint256","name":"_seasonId","type":"uint256"},{"internalType":"uint256","name":"_payoutTier","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"enum MintMethod","name":"_method","type":"uint8"},{"internalType":"address","name":"_to","type":"address"}],"name":"MintFailed","type":"error"},{"inputs":[],"name":"PartiallyPausable__NotPartiallyPaused","type":"error"},{"inputs":[],"name":"PartiallyPausable__PartiallyPaused","type":"error"},{"inputs":[],"name":"Pausable__NotPaused","type":"error"},{"inputs":[],"name":"Pausable__Paused","type":"error"},{"inputs":[{"internalType":"uint256","name":"_payoutTier","type":"uint256"}],"name":"PayoutTierMaxSupplyExceeded","type":"error"},{"inputs":[],"name":"UintUtils__InsufficientHexLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum MintMethod","name":"method","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"seasonId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"payoutTier","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"HorseMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"PartiallyPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"PartiallyUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint256","name":"_seasonId","type":"uint256"},{"internalType":"uint256","name":"_payoutTier","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seasonId","type":"uint256"},{"internalType":"uint256","name":"_payoutTier","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"externalMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seasonId","type":"uint256"},{"internalType":"uint256","name":"_payoutTier","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50613e84806100206000396000f3fe6080604052600436106101145760003560e01c80636352211e116100a0578063b88d4fde11610064578063b88d4fde146103a1578063ba0a44b9146103bd578063c87b56dd146103e6578063e985e9c514610423578063fd152ee71461046057610114565b80636352211e146102b757806370a08231146102f457806395d89b41146103315780639b8b93051461035c578063a22cb4651461037857610114565b806318160ddd116100e757806318160ddd146101da57806323b872dd146102055780632f745c591461022157806342842e0e1461025e5780634f6ccce71461027a57610114565b806301ffc9a71461011957806306fdde0314610156578063081812fc14610181578063095ea7b3146101be575b600080fd5b34801561012557600080fd5b50610140600480360381019061013b9190612d58565b610489565b60405161014d9190612da0565b60405180910390f35b34801561016257600080fd5b5061016b61049b565b6040516101789190612e4b565b60405180910390f35b34801561018d57600080fd5b506101a860048036038101906101a39190612ea3565b6104aa565b6040516101b59190612f11565b60405180910390f35b6101d860048036038101906101d39190612f58565b6104bc565b005b3480156101e657600080fd5b506101ef6104ca565b6040516101fc9190612fa7565b60405180910390f35b61021f600480360381019061021a9190612fc2565b6104d9565b005b34801561022d57600080fd5b5061024860048036038101906102439190612f58565b6104e9565b6040516102559190612fa7565b60405180910390f35b61027860048036038101906102739190612fc2565b6104fd565b005b34801561028657600080fd5b506102a1600480360381019061029c9190612ea3565b61050d565b6040516102ae9190612fa7565b60405180910390f35b3480156102c357600080fd5b506102de60048036038101906102d99190612ea3565b61051f565b6040516102eb9190612f11565b60405180910390f35b34801561030057600080fd5b5061031b60048036038101906103169190613015565b610531565b6040516103289190612fa7565b60405180910390f35b34801561033d57600080fd5b50610346610543565b6040516103539190612e4b565b60405180910390f35b61037660048036038101906103719190613042565b610552565b005b34801561038457600080fd5b5061039f600480360381019061039a91906130c1565b6106e2565b005b6103bb60048036038101906103b69190613236565b6106f0565b005b3480156103c957600080fd5b506103e460048036038101906103df91906132b9565b610702565b005b3480156103f257600080fd5b5061040d60048036038101906104089190612ea3565b6107b3565b60405161041a9190612e4b565b60405180910390f35b34801561042f57600080fd5b5061044a60048036038101906104459190613320565b6107c5565b6040516104579190612da0565b60405180910390f35b34801561046c57600080fd5b50610487600480360381019061048291906132b9565b6107d9565b005b600061049482610818565b9050919050565b60606104a5610889565b905090565b60006104b582610924565b9050919050565b6104c682826109a9565b5050565b60006104d4610b5b565b905090565b6104e4838383610b75565b505050565b60006104f58383610bd1565b905092915050565b610508838383610c35565b505050565b600061051882610c55565b9050919050565b600061052a82610c7e565b9050919050565b600061053c82610d0f565b9050919050565b606061054d610dcd565b905090565b61055a610e68565b15610591576040517f059519da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fbaf1a8b39218df0710a90513bf0dcf53bf025fceec7598c2d0a27eec92649faa6105bb81610e88565b156105f2576040517fd73a2c8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fc610ebb565b600201600085815260200190815260200160002090506000838260020154610624919061338f565b905034811461066c5734816040517f065a653700000000000000000000000000000000000000000000000000000000815260040161066392919061341d565b60405180910390fd5b60008260030154141580156106845750816003015484115b156106cc578382600301546040517f065a65370000000000000000000000000000000000000000000000000000000081526004016106c39291906134a5565b60405180910390fd5b6106da868686600033610ee8565b505050505050565b6106ec82826113d3565b5050565b6106fc8484848461153e565b50505050565b600061070c610ebb565b60060160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1690508061079e57336040517f43839dab0000000000000000000000000000000000000000000000000000000081526004016107959190612f11565b60405180910390fd5b6107ac858585600286610ee8565b5050505050565b60606107be8261159c565b9050919050565b60006107d1838361179b565b905092915050565b7f7dc7a9428f8cc2d7d0a73dfc0f0d4791fa005321ee0ba5d966a60588b12e576c61080381611838565b610811858585600186610ee8565b5050505050565b6000610822611845565b6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6060610893611872565b60000180546108a190613510565b80601f01602080910402602001604051908101604052809291908181526020018280546108cd90613510565b801561091a5780601f106108ef5761010080835404028352916020019161091a565b820191906000526020600020905b8154815290600101906020018083116108fd57829003601f168201915b5050505050905090565b600061092f8261189f565b610965576040517fc1b843ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61096d6118c5565b600301600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6109b48282346118f2565b60006109bf82610c7e565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a26576040517f424a22cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610a695750610a67813361179b565b155b15610aa0576040517f2f5de44f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82610aa96118c5565b600301600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6000610b70610b686118c5565b6000016118f7565b905090565b610b818383833461190c565b610b8b3382611912565b610bc1576040517f2f5de44f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bcc8383836119e7565b505050565b6000610c2d82610bdf6118c5565b60020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611caa90919063ffffffff16565b905092915050565b610c508383836040518060200160405280600081525061153e565b505050565b6000610c7482610c636118c5565b600001611cc490919063ffffffff16565b5080915050919050565b600080610c9e83610c8d6118c5565b600001611cf090919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d06576040517f7e1a7d8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d76576040517f810ff97000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dc6610d816118c5565b60020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d0d565b9050919050565b6060610dd7611872565b6001018054610de590613510565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1190613510565b8015610e5e5780601f10610e3357610100808354040283529160200191610e5e565b820191906000526020600020905b815481529060010190602001808311610e4157829003601f168201915b5050505050905090565b6000610e72611d22565b60000160009054906101000a900460ff16905090565b6000610e92611d4f565b600001600083815260200190815260200160002060009054906101000a900460ff169050919050565b6000807fa9766cf30247385bd274fe73461f870e9ad8351016f172911cfa198f44cc28e590508091505090565b6000610ef2610ebb565b600701549050600081118015610f1a57508084610f0e84610d0f565b610f189190613541565b115b15610f5c57816040517ffe26af11000000000000000000000000000000000000000000000000000000008152600401610f539190612f11565b60405180910390fd5b6000610f66610ebb565b600101600088815260200190815260200160002090508060020160009054906101000a900460ff1680610fa857508060020160019054906101000a900460ff16155b15610fea57866040517faa7ed920000000000000000000000000000000000000000000000000000000008152600401610fe19190612fa7565b60405180910390fd5b6000610ff4610ebb565b600201600088815260200190815260200160002090508060060160009054906101000a900460ff168061103657508060060160019054906101000a900460ff16155b1561107857866040517fb54df80b00000000000000000000000000000000000000000000000000000000815260040161106f9190612fa7565b60405180910390fd5b6000611082610ebb565b905060008160040160008a81526020019081526020016000209050600083600501541180156110c757508260050154886110bb83611d0d565b6110c59190613541565b115b1561110957886040517fa613fc860000000000000000000000000000000000000000000000000000000081526004016111009190612fa7565b60405180910390fd5b60008260000160008c8152602001908152602001600020905060008360080154905060005b8a8110156113b057600081836111449190613541565b90506111598185611d7c90919063ffffffff16565b6111a2578d8d8d8d8d6040517fe60b992a000000000000000000000000000000000000000000000000000000008152600401611199959493929190613638565b60405180910390fd5b6111b58186611d7c90919063ffffffff16565b6111fe578d8d8d8d8d6040517fe60b992a0000000000000000000000000000000000000000000000000000000081526004016111f5959493929190613710565b60405180910390fd5b8686600301600083815260200190815260200160002060008201548160000155600182018160010190816112329190613938565b50600282015481600201556003820154816003015560048201548160040155600582015481600501556006820160009054906101000a900460ff168160060160006101000a81548160ff0219169083151502179055506006820160019054906101000a900460ff168160060160016101000a81548160ff0219169083151502179055509050508786600501600083815260200190815260200160002060008201548160000155600182018160010190816112ec9190613938565b506002820160009054906101000a900460ff168160020160006101000a81548160ff0219169083151502179055506002820160019054906101000a900460ff168160020160016101000a81548160ff0219169083151502179055509050506113548a82611d96565b8c8e8c6002811115611369576113686135c1565b5b7f78da9a89ac3627c32a75c80f4320c7ced2fc3400714cf5a1f7d5668dda3d8d578d8560405161139a929190613a20565b60405180910390a481806001019250505061112e565b80826113bc9190613541565b856008018190555050505050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611438576040517f424a22cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806114416118c5565b60040160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516115329190612da0565b60405180910390a35050565b61154a8484843461190c565b6115543383611912565b61158a576040517f2f5de44f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61159684848484611db4565b50505050565b60606115a78261189f565b6115dd576040517f2382d38000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115e7611872565b90506000816003016000858152602001908152602001600020805461160b90613510565b80601f016020809104026020016040519081016040528092919081815260200182805461163790613510565b80156116845780601f1061165957610100808354040283529160200191611684565b820191906000526020600020905b81548152906001019060200180831161166757829003601f168201915b50505050509050600082600201805461169c90613510565b80601f01602080910402602001604051908101604052809291908181526020018280546116c890613510565b80156117155780601f106116ea57610100808354040283529160200191611715565b820191906000526020600020905b8154815290600101906020018083116116f857829003601f168201915b50505050509050600081510361173057819350505050611796565b60008251111561176657808260405160200161174d929190613a85565b6040516020818303038152906040529350505050611796565b8061177086611e07565b604051602001611781929190613a85565b60405160208183030381529060405293505050505b919050565b60006117a56118c5565b60040160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6118428133611f67565b50565b6000807ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890508091505090565b6000807f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190508091505090565b60006118be826118ad6118c5565b60000161200b90919063ffffffff16565b9050919050565b6000807f3c7bf052874fa81625121783266a03507bd2cd48b16e571c01a04e8dd3fb07a690508091505090565b505050565b600061190582600001612025565b9050919050565b50505050565b600061191d8261189f565b611953576040517fc1b843ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061195e83610c7e565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806119cd57508373ffffffffffffffffffffffffffffffffffffffff166119b584610924565b73ffffffffffffffffffffffffffffffffffffffff16145b806119de57506119dd818561179b565b5b91505092915050565b60006119f282610c7e565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611a59576040517f0f2db4ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611abf576040517f40311a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611aca848484612036565b6000611ad46118c5565b9050611b29838260020160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061204690919063ffffffff16565b50611b7d838260020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d7c90919063ffffffff16565b50611b968385836000016120609092919063ffffffff16565b50600081600301600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b6000611cb98360000183612095565b60001c905092915050565b600080600080611cd78660000186612100565b915091508160001c8160001c9350935050509250929050565b6000611d02836000018360001b612181565b60001c905092915050565b6000611d1b8260000161220a565b9050919050565b6000807f68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea890508091505090565b6000807fb2b4df8db6c86b643bc9671655af7ecab384d088ad8b388456cdc1f36f10ab4590508091505090565b6000611d8e836000018360001b61221b565b905092915050565b611db0828260405180602001604052806000815250612282565b5050565b611dbf8484846119e7565b611dcb848484846122d4565b611e01576040517f9ff10cdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b606060008203611e4e576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611f62565b600082905060005b60008214611e80578080611e6990613aa9565b915050600a82611e799190613b20565b9150611e56565b60008167ffffffffffffffff811115611e9c57611e9b61310b565b5b6040519080825280601f01601f191660200182016040528015611ece5781602001600182028036833780820191505090505b5090505b60008514611f5b57600182611ee79190613b51565b9150600a85611ef69190613b85565b6030611f029190613541565b60f81b818381518110611f1857611f17613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611f549190613b20565b9450611ed2565b8093505050505b919050565b611f71828261244a565b61200757611f948173ffffffffffffffffffffffffffffffffffffffff16612485565b611fab60208460001c6124b890919063ffffffff16565b604051602001611fbc929190613c7d565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ffe9190612e4b565b60405180910390fd5b5050565b600061201d836000018360001b6126d4565b905092915050565b600081600001805490509050919050565b6120418383836126f7565b505050565b6000612058836000018360001b612707565b905092915050565b600061208c846000018460001b8473ffffffffffffffffffffffffffffffffffffffff1660001b6127eb565b90509392505050565b6000826000018054905082106120d7576040517fe637bf3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260000182815481106120ed576120ec613bb6565b5b9060005260206000200154905092915050565b60008083600001805490508310612143576040517f117ec13800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084600001848154811061215b5761215a613bb6565b5b906000526020600020906002020190508060000154816001015492509250509250929050565b600080836001016000848152602001908152602001600020549050600081036121d6576040517ff551fb1400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360000160018203815481106121ef576121ee613bb6565b5b90600052602060002090600202016001015491505092915050565b600081600001805490509050919050565b600061222783836128cd565b61227c5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190505b92915050565b61228c83836128f0565b61229960008484846122d4565b6122cf576040517f9ff10cdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60006122f58473ffffffffffffffffffffffffffffffffffffffff16612a7c565b6123025760019050612442565b60006123c263150b7a0260e01b338887876040516024016123269493929190613d0c565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001613e1d603291398773ffffffffffffffffffffffffffffffffffffffff16612a8f9092919063ffffffff16565b90506000818060200190518101906123da9190613d6d565b90507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050505b949350505050565b600061247d82612458612aa7565b6000016000868152602001908152602001600020600001612ad490919063ffffffff16565b905092915050565b60606124b160148373ffffffffffffffffffffffffffffffffffffffff166124b890919063ffffffff16565b9050919050565b6060600060028360026124cb919061338f565b6124d59190613541565b67ffffffffffffffff8111156124ee576124ed61310b565b5b6040519080825280601f01601f1916602001820160405280156125205781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061255857612557613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106125bc576125bb613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002020190505b600181111561268f577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061263657612635613bb6565b5b1a60f81b82828151811061264d5761264c613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806001900390506125f7565b50600084146126ca576040517fc913478500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8091505092915050565b600080836001016000848152602001908152602001600020541415905092915050565b612702838383612b04565b505050565b600080836001016000848152602001908152602001600020549050600081146127e45760008460000160018660000180549050038154811061274c5761274b613bb6565b5b906000526020600020015490508085600001600184038154811061277357612772613bb6565b5b9060005260206000200181905550818560010160008381526020019081526020016000208190555050836000018054806127b0576127af613d9a565b5b6001900381819060005260206000200160009055905583600101600084815260200190815260200160002060009055600191505b5092915050565b60008084600101600085815260200190815260200160002054905060008103612891578460000160405180604001604052808681526020018581525090806001815401808255809150506001900390600052602060002090600202016000909190919091506000820151816000015560208201518160010155505084600001805490508560010160008681526020019081526020016000208190555060019150506128c6565b828560000160018303815481106128ab576128aa613bb6565b5b90600052602060002090600202016001018190555060009150505b9392505050565b600080836001016000848152602001908152602001600020541415905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612956576040517f23e5311a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61295f8161189f565b15612996576040517f6c35dbd800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129a260008383612036565b60006129ac6118c5565b9050612a01828260020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d7c90919063ffffffff16565b50612a1a8284836000016120609092919063ffffffff16565b50818373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600080823b905060008111915050919050565b6060612a9e8484600085612b71565b90509392505050565b6000807fd3889cc5458b268d0544e5534672df1296288ca3f93cbd39bd6f497a5c62281190508091505090565b6000612afc836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6128cd565b905092915050565b612b0f838383612c8a565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b6c57612b4b611872565b60030160008281526020019081526020016000206000612b6b9190612c8f565b5b505050565b6060612b7c85612a7c565b612bb2576040517f89c35afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bdb9190613e05565b60006040518083038185875af1925050503d8060008114612c18576040519150601f19603f3d011682016040523d82523d6000602084013e612c1d565b606091505b50915091508115612c32578092505050612c82565b600081511115612c455780518082602001fd5b836040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c799190612e4b565b60405180910390fd5b949350505050565b505050565b508054612c9b90613510565b6000825580601f10612cad5750612ccc565b601f016020900490600052602060002090810190612ccb9190612ccf565b5b50565b5b80821115612ce8576000816000905550600101612cd0565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d3581612d00565b8114612d4057600080fd5b50565b600081359050612d5281612d2c565b92915050565b600060208284031215612d6e57612d6d612cf6565b5b6000612d7c84828501612d43565b91505092915050565b60008115159050919050565b612d9a81612d85565b82525050565b6000602082019050612db56000830184612d91565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612df5578082015181840152602081019050612dda565b60008484015250505050565b6000601f19601f8301169050919050565b6000612e1d82612dbb565b612e278185612dc6565b9350612e37818560208601612dd7565b612e4081612e01565b840191505092915050565b60006020820190508181036000830152612e658184612e12565b905092915050565b6000819050919050565b612e8081612e6d565b8114612e8b57600080fd5b50565b600081359050612e9d81612e77565b92915050565b600060208284031215612eb957612eb8612cf6565b5b6000612ec784828501612e8e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612efb82612ed0565b9050919050565b612f0b81612ef0565b82525050565b6000602082019050612f266000830184612f02565b92915050565b612f3581612ef0565b8114612f4057600080fd5b50565b600081359050612f5281612f2c565b92915050565b60008060408385031215612f6f57612f6e612cf6565b5b6000612f7d85828601612f43565b9250506020612f8e85828601612e8e565b9150509250929050565b612fa181612e6d565b82525050565b6000602082019050612fbc6000830184612f98565b92915050565b600080600060608486031215612fdb57612fda612cf6565b5b6000612fe986828701612f43565b9350506020612ffa86828701612f43565b925050604061300b86828701612e8e565b9150509250925092565b60006020828403121561302b5761302a612cf6565b5b600061303984828501612f43565b91505092915050565b60008060006060848603121561305b5761305a612cf6565b5b600061306986828701612e8e565b935050602061307a86828701612e8e565b925050604061308b86828701612e8e565b9150509250925092565b61309e81612d85565b81146130a957600080fd5b50565b6000813590506130bb81613095565b92915050565b600080604083850312156130d8576130d7612cf6565b5b60006130e685828601612f43565b92505060206130f7858286016130ac565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61314382612e01565b810181811067ffffffffffffffff821117156131625761316161310b565b5b80604052505050565b6000613175612cec565b9050613181828261313a565b919050565b600067ffffffffffffffff8211156131a1576131a061310b565b5b6131aa82612e01565b9050602081019050919050565b82818337600083830152505050565b60006131d96131d484613186565b61316b565b9050828152602081018484840111156131f5576131f4613106565b5b6132008482856131b7565b509392505050565b600082601f83011261321d5761321c613101565b5b813561322d8482602086016131c6565b91505092915050565b600080600080608085870312156132505761324f612cf6565b5b600061325e87828801612f43565b945050602061326f87828801612f43565b935050604061328087828801612e8e565b925050606085013567ffffffffffffffff8111156132a1576132a0612cfb565b5b6132ad87828801613208565b91505092959194509250565b600080600080608085870312156132d3576132d2612cf6565b5b60006132e187828801612e8e565b94505060206132f287828801612e8e565b935050604061330387828801612e8e565b925050606061331487828801612f43565b91505092959194509250565b6000806040838503121561333757613336612cf6565b5b600061334585828601612f43565b925050602061335685828601612f43565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061339a82612e6d565b91506133a583612e6d565b92508282026133b381612e6d565b915082820484148315176133ca576133c9613360565b5b5092915050565b7f494e565f4554485f544f54414c00000000000000000000000000000000000000600082015250565b6000613407600d83612dc6565b9150613412826133d1565b602082019050919050565b60006060820190508181036000830152613436816133fa565b90506134456020830185612f98565b6134526040830184612f98565b9392505050565b7f5045525f54585f4552524f520000000000000000000000000000000000000000600082015250565b600061348f600c83612dc6565b915061349a82613459565b602082019050919050565b600060608201905081810360008301526134be81613482565b90506134cd6020830185612f98565b6134da6040830184612f98565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061352857607f821691505b60208210810361353b5761353a6134e1565b5b50919050565b600061354c82612e6d565b915061355783612e6d565b925082820190508082111561356f5761356e613360565b5b92915050565b7f544f4b454e5f43524f505f4153534f43494154494f4e5f4552524f5200000000600082015250565b60006135ab601c83612dc6565b91506135b682613575565b602082019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110613601576136006135c1565b5b50565b6000819050613612826135f0565b919050565b600061362282613604565b9050919050565b61363281613617565b82525050565b600060c08201905081810360008301526136518161359e565b90506136606020830188612f98565b61366d6040830187612f98565b61367a6060830186612f98565b6136876080830185613629565b61369460a0830184612f02565b9695505050505050565b7f544f4b454e5f5041594f55545f544945525f4153534f43494154494f4e5f455260008201527f524f520000000000000000000000000000000000000000000000000000000000602082015250565b60006136fa602383612dc6565b91506137058261369e565b604082019050919050565b600060c0820190508181036000830152613729816136ed565b90506137386020830188612f98565b6137456040830187612f98565b6137526060830186612f98565b61375f6080830185613629565b61376c60a0830184612f02565b9695505050505050565b60008154905061378581613510565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026137ee7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826137b1565b6137f886836137b1565b95508019841693508086168417925050509392505050565b6000819050919050565b600061383561383061382b84612e6d565b613810565b612e6d565b9050919050565b6000819050919050565b61384f8361381a565b61386361385b8261383c565b8484546137be565b825550505050565b600090565b61387861386b565b613883818484613846565b505050565b5b818110156138a75761389c600082613870565b600181019050613889565b5050565b601f8211156138ec576138bd8161378c565b6138c6846137a1565b810160208510156138d5578190505b6138e96138e1856137a1565b830182613888565b50505b505050565b600082821c905092915050565b600061390f600019846008026138f1565b1980831691505092915050565b600061392883836138fe565b9150826002028217905092915050565b818103613946575050613a1e565b61394f82613776565b67ffffffffffffffff8111156139685761396761310b565b5b6139728254613510565b61397d8282856138ab565b6000601f8311600181146139ac576000841561399a578287015490505b6139a4858261391c565b865550613a17565b601f1984166139ba8761378c565b96506139c58661378c565b60005b828110156139ed578489015482556001820191506001850194506020810190506139c8565b86831015613a0a5784890154613a06601f8916826138fe565b8355505b6001600288020188555050505b5050505050505b565b6000604082019050613a356000830185612f02565b613a426020830184612f98565b9392505050565b600081905092915050565b6000613a5f82612dbb565b613a698185613a49565b9350613a79818560208601612dd7565b80840191505092915050565b6000613a918285613a54565b9150613a9d8284613a54565b91508190509392505050565b6000613ab482612e6d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ae657613ae5613360565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613b2b82612e6d565b9150613b3683612e6d565b925082613b4657613b45613af1565b5b828204905092915050565b6000613b5c82612e6d565b9150613b6783612e6d565b9250828203905081811115613b7f57613b7e613360565b5b92915050565b6000613b9082612e6d565b9150613b9b83612e6d565b925082613bab57613baa613af1565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b6000613c1b601783613a49565b9150613c2682613be5565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000613c67601183613a49565b9150613c7282613c31565b601182019050919050565b6000613c8882613c0e565b9150613c948285613a54565b9150613c9f82613c5a565b9150613cab8284613a54565b91508190509392505050565b600081519050919050565b600082825260208201905092915050565b6000613cde82613cb7565b613ce88185613cc2565b9350613cf8818560208601612dd7565b613d0181612e01565b840191505092915050565b6000608082019050613d216000830187612f02565b613d2e6020830186612f02565b613d3b6040830185612f98565b8181036060830152613d4d8184613cd3565b905095945050505050565b600081519050613d6781612d2c565b92915050565b600060208284031215613d8357613d82612cf6565b5b6000613d9184828501613d58565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081905092915050565b6000613ddf82613cb7565b613de98185613dc9565b9350613df9818560208601612dd7565b80840191505092915050565b6000613e118284613dd4565b91508190509291505056fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e746572a2646970667358221220ea8a266ca15d20508a2b6bb06b0c78824352e8de93a238daafc31d8a24fc36fa64736f6c63430008140033
Deployed Bytecode
0x6080604052600436106101145760003560e01c80636352211e116100a0578063b88d4fde11610064578063b88d4fde146103a1578063ba0a44b9146103bd578063c87b56dd146103e6578063e985e9c514610423578063fd152ee71461046057610114565b80636352211e146102b757806370a08231146102f457806395d89b41146103315780639b8b93051461035c578063a22cb4651461037857610114565b806318160ddd116100e757806318160ddd146101da57806323b872dd146102055780632f745c591461022157806342842e0e1461025e5780634f6ccce71461027a57610114565b806301ffc9a71461011957806306fdde0314610156578063081812fc14610181578063095ea7b3146101be575b600080fd5b34801561012557600080fd5b50610140600480360381019061013b9190612d58565b610489565b60405161014d9190612da0565b60405180910390f35b34801561016257600080fd5b5061016b61049b565b6040516101789190612e4b565b60405180910390f35b34801561018d57600080fd5b506101a860048036038101906101a39190612ea3565b6104aa565b6040516101b59190612f11565b60405180910390f35b6101d860048036038101906101d39190612f58565b6104bc565b005b3480156101e657600080fd5b506101ef6104ca565b6040516101fc9190612fa7565b60405180910390f35b61021f600480360381019061021a9190612fc2565b6104d9565b005b34801561022d57600080fd5b5061024860048036038101906102439190612f58565b6104e9565b6040516102559190612fa7565b60405180910390f35b61027860048036038101906102739190612fc2565b6104fd565b005b34801561028657600080fd5b506102a1600480360381019061029c9190612ea3565b61050d565b6040516102ae9190612fa7565b60405180910390f35b3480156102c357600080fd5b506102de60048036038101906102d99190612ea3565b61051f565b6040516102eb9190612f11565b60405180910390f35b34801561030057600080fd5b5061031b60048036038101906103169190613015565b610531565b6040516103289190612fa7565b60405180910390f35b34801561033d57600080fd5b50610346610543565b6040516103539190612e4b565b60405180910390f35b61037660048036038101906103719190613042565b610552565b005b34801561038457600080fd5b5061039f600480360381019061039a91906130c1565b6106e2565b005b6103bb60048036038101906103b69190613236565b6106f0565b005b3480156103c957600080fd5b506103e460048036038101906103df91906132b9565b610702565b005b3480156103f257600080fd5b5061040d60048036038101906104089190612ea3565b6107b3565b60405161041a9190612e4b565b60405180910390f35b34801561042f57600080fd5b5061044a60048036038101906104459190613320565b6107c5565b6040516104579190612da0565b60405180910390f35b34801561046c57600080fd5b50610487600480360381019061048291906132b9565b6107d9565b005b600061049482610818565b9050919050565b60606104a5610889565b905090565b60006104b582610924565b9050919050565b6104c682826109a9565b5050565b60006104d4610b5b565b905090565b6104e4838383610b75565b505050565b60006104f58383610bd1565b905092915050565b610508838383610c35565b505050565b600061051882610c55565b9050919050565b600061052a82610c7e565b9050919050565b600061053c82610d0f565b9050919050565b606061054d610dcd565b905090565b61055a610e68565b15610591576040517f059519da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fbaf1a8b39218df0710a90513bf0dcf53bf025fceec7598c2d0a27eec92649faa6105bb81610e88565b156105f2576040517fd73a2c8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fc610ebb565b600201600085815260200190815260200160002090506000838260020154610624919061338f565b905034811461066c5734816040517f065a653700000000000000000000000000000000000000000000000000000000815260040161066392919061341d565b60405180910390fd5b60008260030154141580156106845750816003015484115b156106cc578382600301546040517f065a65370000000000000000000000000000000000000000000000000000000081526004016106c39291906134a5565b60405180910390fd5b6106da868686600033610ee8565b505050505050565b6106ec82826113d3565b5050565b6106fc8484848461153e565b50505050565b600061070c610ebb565b60060160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1690508061079e57336040517f43839dab0000000000000000000000000000000000000000000000000000000081526004016107959190612f11565b60405180910390fd5b6107ac858585600286610ee8565b5050505050565b60606107be8261159c565b9050919050565b60006107d1838361179b565b905092915050565b7f7dc7a9428f8cc2d7d0a73dfc0f0d4791fa005321ee0ba5d966a60588b12e576c61080381611838565b610811858585600186610ee8565b5050505050565b6000610822611845565b6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6060610893611872565b60000180546108a190613510565b80601f01602080910402602001604051908101604052809291908181526020018280546108cd90613510565b801561091a5780601f106108ef5761010080835404028352916020019161091a565b820191906000526020600020905b8154815290600101906020018083116108fd57829003601f168201915b5050505050905090565b600061092f8261189f565b610965576040517fc1b843ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61096d6118c5565b600301600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6109b48282346118f2565b60006109bf82610c7e565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a26576040517f424a22cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610a695750610a67813361179b565b155b15610aa0576040517f2f5de44f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82610aa96118c5565b600301600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6000610b70610b686118c5565b6000016118f7565b905090565b610b818383833461190c565b610b8b3382611912565b610bc1576040517f2f5de44f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bcc8383836119e7565b505050565b6000610c2d82610bdf6118c5565b60020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611caa90919063ffffffff16565b905092915050565b610c508383836040518060200160405280600081525061153e565b505050565b6000610c7482610c636118c5565b600001611cc490919063ffffffff16565b5080915050919050565b600080610c9e83610c8d6118c5565b600001611cf090919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d06576040517f7e1a7d8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d76576040517f810ff97000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dc6610d816118c5565b60020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d0d565b9050919050565b6060610dd7611872565b6001018054610de590613510565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1190613510565b8015610e5e5780601f10610e3357610100808354040283529160200191610e5e565b820191906000526020600020905b815481529060010190602001808311610e4157829003601f168201915b5050505050905090565b6000610e72611d22565b60000160009054906101000a900460ff16905090565b6000610e92611d4f565b600001600083815260200190815260200160002060009054906101000a900460ff169050919050565b6000807fa9766cf30247385bd274fe73461f870e9ad8351016f172911cfa198f44cc28e590508091505090565b6000610ef2610ebb565b600701549050600081118015610f1a57508084610f0e84610d0f565b610f189190613541565b115b15610f5c57816040517ffe26af11000000000000000000000000000000000000000000000000000000008152600401610f539190612f11565b60405180910390fd5b6000610f66610ebb565b600101600088815260200190815260200160002090508060020160009054906101000a900460ff1680610fa857508060020160019054906101000a900460ff16155b15610fea57866040517faa7ed920000000000000000000000000000000000000000000000000000000008152600401610fe19190612fa7565b60405180910390fd5b6000610ff4610ebb565b600201600088815260200190815260200160002090508060060160009054906101000a900460ff168061103657508060060160019054906101000a900460ff16155b1561107857866040517fb54df80b00000000000000000000000000000000000000000000000000000000815260040161106f9190612fa7565b60405180910390fd5b6000611082610ebb565b905060008160040160008a81526020019081526020016000209050600083600501541180156110c757508260050154886110bb83611d0d565b6110c59190613541565b115b1561110957886040517fa613fc860000000000000000000000000000000000000000000000000000000081526004016111009190612fa7565b60405180910390fd5b60008260000160008c8152602001908152602001600020905060008360080154905060005b8a8110156113b057600081836111449190613541565b90506111598185611d7c90919063ffffffff16565b6111a2578d8d8d8d8d6040517fe60b992a000000000000000000000000000000000000000000000000000000008152600401611199959493929190613638565b60405180910390fd5b6111b58186611d7c90919063ffffffff16565b6111fe578d8d8d8d8d6040517fe60b992a0000000000000000000000000000000000000000000000000000000081526004016111f5959493929190613710565b60405180910390fd5b8686600301600083815260200190815260200160002060008201548160000155600182018160010190816112329190613938565b50600282015481600201556003820154816003015560048201548160040155600582015481600501556006820160009054906101000a900460ff168160060160006101000a81548160ff0219169083151502179055506006820160019054906101000a900460ff168160060160016101000a81548160ff0219169083151502179055509050508786600501600083815260200190815260200160002060008201548160000155600182018160010190816112ec9190613938565b506002820160009054906101000a900460ff168160020160006101000a81548160ff0219169083151502179055506002820160019054906101000a900460ff168160020160016101000a81548160ff0219169083151502179055509050506113548a82611d96565b8c8e8c6002811115611369576113686135c1565b5b7f78da9a89ac3627c32a75c80f4320c7ced2fc3400714cf5a1f7d5668dda3d8d578d8560405161139a929190613a20565b60405180910390a481806001019250505061112e565b80826113bc9190613541565b856008018190555050505050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611438576040517f424a22cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806114416118c5565b60040160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516115329190612da0565b60405180910390a35050565b61154a8484843461190c565b6115543383611912565b61158a576040517f2f5de44f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61159684848484611db4565b50505050565b60606115a78261189f565b6115dd576040517f2382d38000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115e7611872565b90506000816003016000858152602001908152602001600020805461160b90613510565b80601f016020809104026020016040519081016040528092919081815260200182805461163790613510565b80156116845780601f1061165957610100808354040283529160200191611684565b820191906000526020600020905b81548152906001019060200180831161166757829003601f168201915b50505050509050600082600201805461169c90613510565b80601f01602080910402602001604051908101604052809291908181526020018280546116c890613510565b80156117155780601f106116ea57610100808354040283529160200191611715565b820191906000526020600020905b8154815290600101906020018083116116f857829003601f168201915b50505050509050600081510361173057819350505050611796565b60008251111561176657808260405160200161174d929190613a85565b6040516020818303038152906040529350505050611796565b8061177086611e07565b604051602001611781929190613a85565b60405160208183030381529060405293505050505b919050565b60006117a56118c5565b60040160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6118428133611f67565b50565b6000807ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890508091505090565b6000807f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190508091505090565b60006118be826118ad6118c5565b60000161200b90919063ffffffff16565b9050919050565b6000807f3c7bf052874fa81625121783266a03507bd2cd48b16e571c01a04e8dd3fb07a690508091505090565b505050565b600061190582600001612025565b9050919050565b50505050565b600061191d8261189f565b611953576040517fc1b843ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061195e83610c7e565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806119cd57508373ffffffffffffffffffffffffffffffffffffffff166119b584610924565b73ffffffffffffffffffffffffffffffffffffffff16145b806119de57506119dd818561179b565b5b91505092915050565b60006119f282610c7e565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611a59576040517f0f2db4ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611abf576040517f40311a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611aca848484612036565b6000611ad46118c5565b9050611b29838260020160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061204690919063ffffffff16565b50611b7d838260020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d7c90919063ffffffff16565b50611b968385836000016120609092919063ffffffff16565b50600081600301600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b6000611cb98360000183612095565b60001c905092915050565b600080600080611cd78660000186612100565b915091508160001c8160001c9350935050509250929050565b6000611d02836000018360001b612181565b60001c905092915050565b6000611d1b8260000161220a565b9050919050565b6000807f68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea890508091505090565b6000807fb2b4df8db6c86b643bc9671655af7ecab384d088ad8b388456cdc1f36f10ab4590508091505090565b6000611d8e836000018360001b61221b565b905092915050565b611db0828260405180602001604052806000815250612282565b5050565b611dbf8484846119e7565b611dcb848484846122d4565b611e01576040517f9ff10cdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b606060008203611e4e576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611f62565b600082905060005b60008214611e80578080611e6990613aa9565b915050600a82611e799190613b20565b9150611e56565b60008167ffffffffffffffff811115611e9c57611e9b61310b565b5b6040519080825280601f01601f191660200182016040528015611ece5781602001600182028036833780820191505090505b5090505b60008514611f5b57600182611ee79190613b51565b9150600a85611ef69190613b85565b6030611f029190613541565b60f81b818381518110611f1857611f17613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611f549190613b20565b9450611ed2565b8093505050505b919050565b611f71828261244a565b61200757611f948173ffffffffffffffffffffffffffffffffffffffff16612485565b611fab60208460001c6124b890919063ffffffff16565b604051602001611fbc929190613c7d565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ffe9190612e4b565b60405180910390fd5b5050565b600061201d836000018360001b6126d4565b905092915050565b600081600001805490509050919050565b6120418383836126f7565b505050565b6000612058836000018360001b612707565b905092915050565b600061208c846000018460001b8473ffffffffffffffffffffffffffffffffffffffff1660001b6127eb565b90509392505050565b6000826000018054905082106120d7576040517fe637bf3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260000182815481106120ed576120ec613bb6565b5b9060005260206000200154905092915050565b60008083600001805490508310612143576040517f117ec13800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084600001848154811061215b5761215a613bb6565b5b906000526020600020906002020190508060000154816001015492509250509250929050565b600080836001016000848152602001908152602001600020549050600081036121d6576040517ff551fb1400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360000160018203815481106121ef576121ee613bb6565b5b90600052602060002090600202016001015491505092915050565b600081600001805490509050919050565b600061222783836128cd565b61227c5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190505b92915050565b61228c83836128f0565b61229960008484846122d4565b6122cf576040517f9ff10cdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60006122f58473ffffffffffffffffffffffffffffffffffffffff16612a7c565b6123025760019050612442565b60006123c263150b7a0260e01b338887876040516024016123269493929190613d0c565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001613e1d603291398773ffffffffffffffffffffffffffffffffffffffff16612a8f9092919063ffffffff16565b90506000818060200190518101906123da9190613d6d565b90507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050505b949350505050565b600061247d82612458612aa7565b6000016000868152602001908152602001600020600001612ad490919063ffffffff16565b905092915050565b60606124b160148373ffffffffffffffffffffffffffffffffffffffff166124b890919063ffffffff16565b9050919050565b6060600060028360026124cb919061338f565b6124d59190613541565b67ffffffffffffffff8111156124ee576124ed61310b565b5b6040519080825280601f01601f1916602001820160405280156125205781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061255857612557613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106125bc576125bb613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002020190505b600181111561268f577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061263657612635613bb6565b5b1a60f81b82828151811061264d5761264c613bb6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806001900390506125f7565b50600084146126ca576040517fc913478500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8091505092915050565b600080836001016000848152602001908152602001600020541415905092915050565b612702838383612b04565b505050565b600080836001016000848152602001908152602001600020549050600081146127e45760008460000160018660000180549050038154811061274c5761274b613bb6565b5b906000526020600020015490508085600001600184038154811061277357612772613bb6565b5b9060005260206000200181905550818560010160008381526020019081526020016000208190555050836000018054806127b0576127af613d9a565b5b6001900381819060005260206000200160009055905583600101600084815260200190815260200160002060009055600191505b5092915050565b60008084600101600085815260200190815260200160002054905060008103612891578460000160405180604001604052808681526020018581525090806001815401808255809150506001900390600052602060002090600202016000909190919091506000820151816000015560208201518160010155505084600001805490508560010160008681526020019081526020016000208190555060019150506128c6565b828560000160018303815481106128ab576128aa613bb6565b5b90600052602060002090600202016001018190555060009150505b9392505050565b600080836001016000848152602001908152602001600020541415905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612956576040517f23e5311a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61295f8161189f565b15612996576040517f6c35dbd800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129a260008383612036565b60006129ac6118c5565b9050612a01828260020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d7c90919063ffffffff16565b50612a1a8284836000016120609092919063ffffffff16565b50818373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600080823b905060008111915050919050565b6060612a9e8484600085612b71565b90509392505050565b6000807fd3889cc5458b268d0544e5534672df1296288ca3f93cbd39bd6f497a5c62281190508091505090565b6000612afc836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6128cd565b905092915050565b612b0f838383612c8a565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b6c57612b4b611872565b60030160008281526020019081526020016000206000612b6b9190612c8f565b5b505050565b6060612b7c85612a7c565b612bb2576040517f89c35afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bdb9190613e05565b60006040518083038185875af1925050503d8060008114612c18576040519150601f19603f3d011682016040523d82523d6000602084013e612c1d565b606091505b50915091508115612c32578092505050612c82565b600081511115612c455780518082602001fd5b836040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c799190612e4b565b60405180910390fd5b949350505050565b505050565b508054612c9b90613510565b6000825580601f10612cad5750612ccc565b601f016020900490600052602060002090810190612ccb9190612ccf565b5b50565b5b80821115612ce8576000816000905550600101612cd0565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d3581612d00565b8114612d4057600080fd5b50565b600081359050612d5281612d2c565b92915050565b600060208284031215612d6e57612d6d612cf6565b5b6000612d7c84828501612d43565b91505092915050565b60008115159050919050565b612d9a81612d85565b82525050565b6000602082019050612db56000830184612d91565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612df5578082015181840152602081019050612dda565b60008484015250505050565b6000601f19601f8301169050919050565b6000612e1d82612dbb565b612e278185612dc6565b9350612e37818560208601612dd7565b612e4081612e01565b840191505092915050565b60006020820190508181036000830152612e658184612e12565b905092915050565b6000819050919050565b612e8081612e6d565b8114612e8b57600080fd5b50565b600081359050612e9d81612e77565b92915050565b600060208284031215612eb957612eb8612cf6565b5b6000612ec784828501612e8e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612efb82612ed0565b9050919050565b612f0b81612ef0565b82525050565b6000602082019050612f266000830184612f02565b92915050565b612f3581612ef0565b8114612f4057600080fd5b50565b600081359050612f5281612f2c565b92915050565b60008060408385031215612f6f57612f6e612cf6565b5b6000612f7d85828601612f43565b9250506020612f8e85828601612e8e565b9150509250929050565b612fa181612e6d565b82525050565b6000602082019050612fbc6000830184612f98565b92915050565b600080600060608486031215612fdb57612fda612cf6565b5b6000612fe986828701612f43565b9350506020612ffa86828701612f43565b925050604061300b86828701612e8e565b9150509250925092565b60006020828403121561302b5761302a612cf6565b5b600061303984828501612f43565b91505092915050565b60008060006060848603121561305b5761305a612cf6565b5b600061306986828701612e8e565b935050602061307a86828701612e8e565b925050604061308b86828701612e8e565b9150509250925092565b61309e81612d85565b81146130a957600080fd5b50565b6000813590506130bb81613095565b92915050565b600080604083850312156130d8576130d7612cf6565b5b60006130e685828601612f43565b92505060206130f7858286016130ac565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61314382612e01565b810181811067ffffffffffffffff821117156131625761316161310b565b5b80604052505050565b6000613175612cec565b9050613181828261313a565b919050565b600067ffffffffffffffff8211156131a1576131a061310b565b5b6131aa82612e01565b9050602081019050919050565b82818337600083830152505050565b60006131d96131d484613186565b61316b565b9050828152602081018484840111156131f5576131f4613106565b5b6132008482856131b7565b509392505050565b600082601f83011261321d5761321c613101565b5b813561322d8482602086016131c6565b91505092915050565b600080600080608085870312156132505761324f612cf6565b5b600061325e87828801612f43565b945050602061326f87828801612f43565b935050604061328087828801612e8e565b925050606085013567ffffffffffffffff8111156132a1576132a0612cfb565b5b6132ad87828801613208565b91505092959194509250565b600080600080608085870312156132d3576132d2612cf6565b5b60006132e187828801612e8e565b94505060206132f287828801612e8e565b935050604061330387828801612e8e565b925050606061331487828801612f43565b91505092959194509250565b6000806040838503121561333757613336612cf6565b5b600061334585828601612f43565b925050602061335685828601612f43565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061339a82612e6d565b91506133a583612e6d565b92508282026133b381612e6d565b915082820484148315176133ca576133c9613360565b5b5092915050565b7f494e565f4554485f544f54414c00000000000000000000000000000000000000600082015250565b6000613407600d83612dc6565b9150613412826133d1565b602082019050919050565b60006060820190508181036000830152613436816133fa565b90506134456020830185612f98565b6134526040830184612f98565b9392505050565b7f5045525f54585f4552524f520000000000000000000000000000000000000000600082015250565b600061348f600c83612dc6565b915061349a82613459565b602082019050919050565b600060608201905081810360008301526134be81613482565b90506134cd6020830185612f98565b6134da6040830184612f98565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061352857607f821691505b60208210810361353b5761353a6134e1565b5b50919050565b600061354c82612e6d565b915061355783612e6d565b925082820190508082111561356f5761356e613360565b5b92915050565b7f544f4b454e5f43524f505f4153534f43494154494f4e5f4552524f5200000000600082015250565b60006135ab601c83612dc6565b91506135b682613575565b602082019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110613601576136006135c1565b5b50565b6000819050613612826135f0565b919050565b600061362282613604565b9050919050565b61363281613617565b82525050565b600060c08201905081810360008301526136518161359e565b90506136606020830188612f98565b61366d6040830187612f98565b61367a6060830186612f98565b6136876080830185613629565b61369460a0830184612f02565b9695505050505050565b7f544f4b454e5f5041594f55545f544945525f4153534f43494154494f4e5f455260008201527f524f520000000000000000000000000000000000000000000000000000000000602082015250565b60006136fa602383612dc6565b91506137058261369e565b604082019050919050565b600060c0820190508181036000830152613729816136ed565b90506137386020830188612f98565b6137456040830187612f98565b6137526060830186612f98565b61375f6080830185613629565b61376c60a0830184612f02565b9695505050505050565b60008154905061378581613510565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026137ee7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826137b1565b6137f886836137b1565b95508019841693508086168417925050509392505050565b6000819050919050565b600061383561383061382b84612e6d565b613810565b612e6d565b9050919050565b6000819050919050565b61384f8361381a565b61386361385b8261383c565b8484546137be565b825550505050565b600090565b61387861386b565b613883818484613846565b505050565b5b818110156138a75761389c600082613870565b600181019050613889565b5050565b601f8211156138ec576138bd8161378c565b6138c6846137a1565b810160208510156138d5578190505b6138e96138e1856137a1565b830182613888565b50505b505050565b600082821c905092915050565b600061390f600019846008026138f1565b1980831691505092915050565b600061392883836138fe565b9150826002028217905092915050565b818103613946575050613a1e565b61394f82613776565b67ffffffffffffffff8111156139685761396761310b565b5b6139728254613510565b61397d8282856138ab565b6000601f8311600181146139ac576000841561399a578287015490505b6139a4858261391c565b865550613a17565b601f1984166139ba8761378c565b96506139c58661378c565b60005b828110156139ed578489015482556001820191506001850194506020810190506139c8565b86831015613a0a5784890154613a06601f8916826138fe565b8355505b6001600288020188555050505b5050505050505b565b6000604082019050613a356000830185612f02565b613a426020830184612f98565b9392505050565b600081905092915050565b6000613a5f82612dbb565b613a698185613a49565b9350613a79818560208601612dd7565b80840191505092915050565b6000613a918285613a54565b9150613a9d8284613a54565b91508190509392505050565b6000613ab482612e6d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ae657613ae5613360565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613b2b82612e6d565b9150613b3683612e6d565b925082613b4657613b45613af1565b5b828204905092915050565b6000613b5c82612e6d565b9150613b6783612e6d565b9250828203905081811115613b7f57613b7e613360565b5b92915050565b6000613b9082612e6d565b9150613b9b83612e6d565b925082613bab57613baa613af1565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b6000613c1b601783613a49565b9150613c2682613be5565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000613c67601183613a49565b9150613c7282613c31565b601182019050919050565b6000613c8882613c0e565b9150613c948285613a54565b9150613c9f82613c5a565b9150613cab8284613a54565b91508190509392505050565b600081519050919050565b600082825260208201905092915050565b6000613cde82613cb7565b613ce88185613cc2565b9350613cf8818560208601612dd7565b613d0181612e01565b840191505092915050565b6000608082019050613d216000830187612f02565b613d2e6020830186612f02565b613d3b6040830185612f98565b8181036060830152613d4d8184613cd3565b905095945050505050565b600081519050613d6781612d2c565b92915050565b600060208284031215613d8357613d82612cf6565b5b6000613d9184828501613d58565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081905092915050565b6000613ddf82613cb7565b613de98185613dc9565b9350613df9818560208601612dd7565b80840191505092915050565b6000613e118284613dd4565b91508190509291505056fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e746572a2646970667358221220ea8a266ca15d20508a2b6bb06b0c78824352e8de93a238daafc31d8a24fc36fa64736f6c63430008140033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.