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
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Archetype
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Archetype v0.5.2 - ERC1155 // // d8888 888 888 // d88888 888 888 // d88P888 888 888 // d88P 888 888d888 .d8888b 88888b. .d88b. 888888 888 888 88888b. .d88b. // d88P 888 888P" d88P" 888 "88b d8P Y8b 888 888 888 888 "88b d8P Y8b // d88P 888 888 888 888 888 88888888 888 888 888 888 888 88888888 // d8888888888 888 Y88b. 888 888 Y8b. Y88b. Y88b 888 888 d88P Y8b. // d88P 888 888 "Y8888P 888 888 "Y8888 "Y888 "Y88888 88888P" "Y8888 // 888 888 // Y8b d88P 888 // "Y88P" 888 pragma solidity ^0.8.4; import "./ArchetypeLogic.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "solady/src/utils/LibString.sol"; import "closedsea/src/OperatorFilterer.sol"; import "@openzeppelin/contracts-upgradeable/token/common/ERC2981Upgradeable.sol"; contract Archetype is Initializable, ERC1155Upgradeable, OperatorFilterer, OwnableUpgradeable, ERC2981Upgradeable { // // EVENTS // event Invited(bytes32 indexed key, bytes32 indexed cid); event Referral(address indexed affiliate, address token, uint128 wad, uint256 numMints); event Withdrawal(address indexed src, address token, uint128 wad); // // VARIABLES // mapping(bytes32 => DutchInvite) public invites; mapping(address => mapping(bytes32 => uint256)) private _minted; mapping(bytes32 => uint256) private _listSupply; mapping(address => OwnerBalance) private _ownerBalance; mapping(address => mapping(address => uint128)) private _affiliateBalance; uint256[] private _tokenSupply; Config public config; Options public options; string public name; string public symbol; string public provenance; // // METHODS // function initialize( string memory _name, string memory _symbol, Config calldata config_, address _receiver ) external initializer { name = _name; symbol = _symbol; __ERC1155_init(""); // check max bps not reached and min platform fee. if ( config_.affiliateFee > MAXBPS || config_.platformFee > MAXBPS || config_.platformFee < 500 || config_.discounts.affiliateDiscount > MAXBPS || config_.affiliateSigner == address(0) || config_.maxBatchSize == 0 ) { revert InvalidConfig(); } // ensure mint tiers are correctly ordered from highest to lowest. for (uint256 i = 1; i < config_.discounts.mintTiers.length; i++) { if ( config_.discounts.mintTiers[i].mintDiscount > MAXBPS || config_.discounts.mintTiers[i].numMints > config_.discounts.mintTiers[i - 1].numMints ) { revert InvalidConfig(); } } config = config_; _tokenSupply = new uint256[](config_.maxSupply.length); __Ownable_init(); if (config.ownerAltPayout != address(0)) { setDefaultRoyalty(config.ownerAltPayout, config.defaultRoyalty); } else { setDefaultRoyalty(_receiver, config.defaultRoyalty); } } // // PUBLIC // // use mintToken for non-random lists function mint( Auth calldata auth, uint256 quantity, address affiliate, bytes calldata signature ) external payable { mintTo(auth, quantity, msg.sender, 0, affiliate, signature); } // tokenId is ignored in case of random list function mintToken( Auth calldata auth, uint256 quantity, uint256 tokenId, address affiliate, bytes calldata signature ) external payable { mintTo(auth, quantity, msg.sender, tokenId, affiliate, signature); } function mintTokens( Auth[] calldata auth, uint256[] calldata quantity, uint256[] calldata tokenId, address affiliate, bytes calldata signature ) external payable { for (uint256 i = 0; i < auth.length; i++) { mintTo(auth[i], quantity[i], msg.sender, tokenId[i], affiliate, signature); } } // batch mint only supported on non random and non booster lists function batchMintTo( Auth calldata auth, address[] calldata toList, uint256[] calldata quantityList, uint256[] calldata tokenIdList, address affiliate, bytes calldata signature ) external payable { if (quantityList.length != toList.length || quantityList.length != tokenIdList.length) { revert InvalidConfig(); } DutchInvite storage invite = invites[auth.key]; if (invite.randomize || invite.unitSize > 1) { revert NotSupported(); } ValidationArgs memory args; { args = ValidationArgs({ owner: owner(), affiliate: affiliate, quantities: quantityList, tokenIds: tokenIdList }); } ArchetypeLogic.validateMint( invite, config, auth, _minted, _listSupply, _tokenSupply, signature, args ); for (uint256 i = 0; i < toList.length; i++) { bytes memory _data; _mint(toList[i], tokenIdList[i], quantityList[i], _data); _tokenSupply[tokenIdList[i] - 1] += quantityList[i]; } uint256 quantity = 0; for (uint256 i = 0; i < quantityList.length; i++) { quantity += quantityList[i]; } if (invite.limit < invite.maxSupply) { _minted[msg.sender][auth.key] += quantity; } if (invite.maxSupply < 2**32 - 1) { _listSupply[auth.key] += quantity; } ArchetypeLogic.updateBalances( invite, config, _ownerBalance, _affiliateBalance, affiliate, quantity ); } function mintTo( Auth calldata auth, uint256 quantity, address to, uint256 tokenId, // only used if randomizer=false address affiliate, bytes calldata signature ) public payable { DutchInvite storage i = invites[auth.key]; if (i.unitSize > 1) { quantity = quantity * i.unitSize; } ValidationArgs memory args; { uint256[] memory tokenIds; uint256[] memory quantities; if (i.randomize) { // to avoid stack too deep errors uint256 seed = ArchetypeLogic.random(); tokenIds = ArchetypeLogic.getRandomTokenIds( _tokenSupply, config.maxSupply, i.tokenIds, quantity, seed ); quantities = new uint256[](tokenIds.length); for (uint256 j = 0; j < tokenIds.length; j++) { quantities[j] = 1; } } else { tokenIds = new uint256[](1); tokenIds[0] = tokenId; quantities = new uint256[](1); quantities[0] = quantity; } args = ValidationArgs({ owner: owner(), affiliate: affiliate, quantities: quantities, tokenIds: tokenIds }); } ArchetypeLogic.validateMint( i, config, auth, _minted, _listSupply, _tokenSupply, signature, args ); for (uint256 j = 0; j < args.tokenIds.length; j++) { bytes memory _data; _mint(to, args.tokenIds[j], args.quantities[j], _data); _tokenSupply[args.tokenIds[j] - 1] += args.quantities[j]; } if (i.limit < i.maxSupply) { _minted[msg.sender][auth.key] += quantity; } if (i.maxSupply < 2**32 - 1) { _listSupply[auth.key] += quantity; } ArchetypeLogic.updateBalances(i, config, _ownerBalance, _affiliateBalance, affiliate, quantity); } function uri(uint256 tokenId) public view override returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); return bytes(config.baseUri).length != 0 ? string(abi.encodePacked(config.baseUri, LibString.toString(tokenId))) : ""; } function withdraw() external { address[] memory tokens = new address[](1); tokens[0] = address(0); withdrawTokens(tokens); } function withdrawTokens(address[] memory tokens) public { ArchetypeLogic.withdrawTokens(config, _ownerBalance, _affiliateBalance, owner(), tokens); } function ownerBalance() external view returns (OwnerBalance memory) { return _ownerBalance[address(0)]; } function ownerBalanceToken(address token) external view returns (OwnerBalance memory) { return _ownerBalance[token]; } function affiliateBalance(address affiliate) external view returns (uint128) { return _affiliateBalance[affiliate][address(0)]; } function affiliateBalanceToken(address affiliate, address token) external view returns (uint128) { return _affiliateBalance[affiliate][token]; } function minted(address minter, bytes32 key) external view returns (uint256) { return _minted[minter][key]; } function listSupply(bytes32 key) external view returns (uint256) { return _listSupply[key]; } function platform() external pure returns (address) { return PLATFORM; } function tokenSupply(uint256 tokenId) external view returns (uint256) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); return _tokenSupply[tokenId - 1]; } function totalSupply() external view returns (uint256) { uint256 supply = 0; for (uint256 i = 0; i < _tokenSupply.length; i++) { supply += _tokenSupply[i]; } return supply; } function maxSupply() external view returns (uint32[] memory) { return config.maxSupply; } // // OWNER ONLY // function setBaseURI(string memory baseUri) external onlyOwner { if (options.uriLocked) { revert LockedForever(); } config.baseUri = baseUri; } /// @notice the password is "forever" function lockURI(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.uriLocked = true; } /// @notice the password is "forever" // max supply cannot subceed total supply. Be careful changing. function setMaxSupply(uint32[] memory newMaxSupply, string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } if (options.maxSupplyLocked) { revert LockedForever(); } for (uint256 i = 0; i < _tokenSupply.length; i++) { if (newMaxSupply[i] < _tokenSupply[i]) { revert MaxSupplyExceeded(); } } // increase size of token supply array to match new max supply for (uint256 i = _tokenSupply.length; i < newMaxSupply.length; i++) { _tokenSupply.push(0); } config.maxSupply = newMaxSupply; } /// @notice the password is "forever" function lockMaxSupply(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.maxSupplyLocked = true; } function setAffiliateFee(uint16 affiliateFee) external onlyOwner { if (options.affiliateFeeLocked) { revert LockedForever(); } if (affiliateFee > MAXBPS) { revert InvalidConfig(); } config.affiliateFee = affiliateFee; } /// @notice the password is "forever" function lockAffiliateFee(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.affiliateFeeLocked = true; } function setDiscounts(Discount calldata discounts) external onlyOwner { if (options.discountsLocked) { revert LockedForever(); } if (discounts.affiliateDiscount > MAXBPS) { revert InvalidConfig(); } // ensure mint tiers are correctly ordered from highest to lowest. for (uint256 i = 1; i < discounts.mintTiers.length; i++) { if ( discounts.mintTiers[i].mintDiscount > MAXBPS || discounts.mintTiers[i].numMints > discounts.mintTiers[i - 1].numMints ) { revert InvalidConfig(); } } config.discounts = discounts; } /// @notice the password is "forever" function lockDiscounts(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.discountsLocked = true; } /// @notice Set BAYC-style provenance once it's calculated function setProvenanceHash(string memory provenanceHash) external onlyOwner { if (options.provenanceHashLocked) { revert LockedForever(); } provenance = provenanceHash; } /// @notice the password is "forever" function lockProvenanceHash(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.provenanceHashLocked = true; } function setOwnerAltPayout(address ownerAltPayout) external onlyOwner { if (options.ownerAltPayoutLocked) { revert LockedForever(); } config.ownerAltPayout = ownerAltPayout; } /// @notice the password is "forever" function lockOwnerAltPayout(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.ownerAltPayoutLocked = true; } function setMaxBatchSize(uint32 maxBatchSize) external onlyOwner { config.maxBatchSize = maxBatchSize; } function setInvite( bytes32 _key, bytes32 _cid, Invite calldata _invite ) external onlyOwner { invites[_key] = DutchInvite({ price: _invite.price, reservePrice: _invite.price, delta: 0, start: _invite.start, end: _invite.end, limit: _invite.limit, maxSupply: _invite.maxSupply, interval: 0, unitSize: _invite.unitSize, randomize: _invite.randomize, tokenIds: _invite.tokenIds, tokenAddress: _invite.tokenAddress }); emit Invited(_key, _cid); } function setDutchInvite( bytes32 _key, bytes32 _cid, DutchInvite memory _dutchInvite ) external onlyOwner { if (_dutchInvite.start < block.timestamp) { _dutchInvite.start = uint32(block.timestamp); } invites[_key] = _dutchInvite; emit Invited(_key, _cid); } // // PLATFORM ONLY // function setSuperAffiliatePayout(address superAffiliatePayout) external onlyPlatform { config.superAffiliatePayout = superAffiliatePayout; } // // INTERNAL // function _startTokenId() internal view virtual returns (uint256) { return 1; } function _exists(uint256 tokenId) internal view returns (bool) { return tokenId > 0 && tokenId <= _tokenSupply.length; } modifier onlyPlatform() { if (msg.sender != PLATFORM) { revert NotPlatform(); } _; } //ERC2981 ROYALTY function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155Upgradeable, ERC2981Upgradeable) returns (bool) { // Supports the following `interfaceId`s: // - IERC165: 0x01ffc9a7 // - IERC721: 0x80ac58cd // - IERC721Metadata: 0x5b5e139f // - IERC2981: 0x2a55205a return ERC1155Upgradeable.supportsInterface(interfaceId) || ERC2981Upgradeable.supportsInterface(interfaceId); } function setDefaultRoyalty(address receiver, uint16 feeNumerator) public onlyOwner { config.defaultRoyalty = feeNumerator; _setDefaultRoyalty(receiver, feeNumerator); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981Upgradeable is IERC165Upgradeable { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol) pragma solidity ^0.8.0; import "../../interfaces/IERC2981Upgradeable.sol"; import "../../utils/introspection/ERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC2981Upgradeable is Initializable, IERC2981Upgradeable, ERC165Upgradeable { function __ERC2981_init() internal onlyInitializing { } function __ERC2981_init_unchained() internal onlyInitializing { } struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC165Upgradeable) returns (bool) { return interfaceId == type(IERC2981Upgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981Upgradeable */ function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) { RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId]; if (royalty.receiver == address(0)) { royalty = _defaultRoyaltyInfo; } uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator(); return (royalty.receiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: invalid receiver"); _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty( uint256 tokenId, address receiver, uint96 feeNumerator ) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: Invalid parameters"); _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[48] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155Upgradeable.sol"; import "./IERC1155ReceiverUpgradeable.sol"; import "./extensions/IERC1155MetadataURIUpgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../utils/introspection/ERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable { using AddressUpgradeable for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ function __ERC1155_init(string memory uri_) internal onlyInitializing { __ERC1155_init_unchained(uri_); } function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC1155Upgradeable).interfaceId || interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[47] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155Upgradeable.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155ReceiverUpgradeable is IERC165Upgradeable { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Optimized and flexible operator filterer to abide to OpenSea's /// mandatory on-chain royalty enforcement in order for new collections to /// receive royalties. /// For more information, see: /// See: https://github.com/ProjectOpenSea/operator-filter-registry abstract contract OperatorFilterer { /// @dev The default OpenSea operator blocklist subscription. address internal constant _DEFAULT_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6; /// @dev The OpenSea operator filter registry. address internal constant _OPERATOR_FILTER_REGISTRY = 0x000000000000AAeB6D7670E522A718067333cd4E; /// @dev Registers the current contract to OpenSea's operator filter, /// and subscribe to the default OpenSea operator blocklist. /// Note: Will not revert nor update existing settings for repeated registration. function _registerForOperatorFiltering() internal virtual { _registerForOperatorFiltering(_DEFAULT_SUBSCRIPTION, true); } /// @dev Registers the current contract to OpenSea's operator filter. /// Note: Will not revert nor update existing settings for repeated registration. function _registerForOperatorFiltering(address subscriptionOrRegistrantToCopy, bool subscribe) internal virtual { /// @solidity memory-safe-assembly assembly { let functionSelector := 0x7d3e3dbe // `registerAndSubscribe(address,address)`. // Clean the upper 96 bits of `subscriptionOrRegistrantToCopy` in case they are dirty. subscriptionOrRegistrantToCopy := shr(96, shl(96, subscriptionOrRegistrantToCopy)) for {} iszero(subscribe) {} { if iszero(subscriptionOrRegistrantToCopy) { functionSelector := 0x4420e486 // `register(address)`. break } functionSelector := 0xa0af2903 // `registerAndCopyEntries(address,address)`. break } // Store the function selector. mstore(0x00, shl(224, functionSelector)) // Store the `address(this)`. mstore(0x04, address()) // Store the `subscriptionOrRegistrantToCopy`. mstore(0x24, subscriptionOrRegistrantToCopy) // Register into the registry. if iszero(call(gas(), _OPERATOR_FILTER_REGISTRY, 0, 0x00, 0x44, 0x00, 0x04)) { // If the function selector has not been overwritten, // it is an out-of-gas error. if eq(shr(224, mload(0x00)), functionSelector) { // To prevent gas under-estimation. revert(0, 0) } } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, because of Solidity's memory size limits. mstore(0x24, 0) } } /// @dev Modifier to guard a function and revert if the caller is a blocked operator. modifier onlyAllowedOperator(address from) virtual { if (from != msg.sender) { if (!_isPriorityOperator(msg.sender)) { if (_operatorFilteringEnabled()) _revertIfBlocked(msg.sender); } } _; } /// @dev Modifier to guard a function from approving a blocked operator.. modifier onlyAllowedOperatorApproval(address operator) virtual { if (!_isPriorityOperator(operator)) { if (_operatorFilteringEnabled()) _revertIfBlocked(operator); } _; } /// @dev Helper function that reverts if the `operator` is blocked by the registry. function _revertIfBlocked(address operator) private view { /// @solidity memory-safe-assembly assembly { // Store the function selector of `isOperatorAllowed(address,address)`, // shifted left by 6 bytes, which is enough for 8tb of memory. // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xc6171134001122334455) // Store the `address(this)`. mstore(0x1a, address()) // Store the `operator`. mstore(0x3a, operator) // `isOperatorAllowed` always returns true if it does not revert. if iszero(staticcall(gas(), _OPERATOR_FILTER_REGISTRY, 0x16, 0x44, 0x00, 0x00)) { // Bubble up the revert if the staticcall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } // We'll skip checking if `from` is inside the blacklist. // Even though that can block transferring out of wrapper contracts, // we don't want tokens to be stuck. // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev For deriving contracts to override, so that operator filtering /// can be turned on / off. /// Returns true by default. function _operatorFilteringEnabled() internal view virtual returns (bool) { return true; } /// @dev For deriving contracts to override, so that preferred marketplaces can /// skip operator filtering, helping users save gas. /// Returns false for all inputs by default. function _isPriorityOperator(address) internal view virtual returns (bool) { return false; } }
// SPDX-License-Identifier: MIT // ArchetypeLogic v0.5.2 - ERC1155 // // d8888 888 888 // d88888 888 888 // d88P888 888 888 // d88P 888 888d888 .d8888b 88888b. .d88b. 888888 888 888 88888b. .d88b. // d88P 888 888P" d88P" 888 "88b d8P Y8b 888 888 888 888 "88b d8P Y8b // d88P 888 888 888 888 888 88888888 888 888 888 888 888 88888888 // d8888888888 888 Y88b. 888 888 Y8b. Y88b. Y88b 888 888 d88P Y8b. // d88P 888 888 "Y8888P 888 888 "Y8888 "Y888 "Y88888 88888P" "Y8888 // 888 888 // Y8b d88P 888 // "Y88P" 888 pragma solidity ^0.8.4; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "solady/src/utils/MerkleProofLib.sol"; import "solady/src/utils/ECDSA.sol"; error InvalidConfig(); error MintNotYetStarted(); error MintEnded(); error WalletUnauthorizedToMint(); error InsufficientEthSent(); error ExcessiveEthSent(); error Erc20BalanceTooLow(); error MaxSupplyExceeded(); error ListMaxSupplyExceeded(); error NumberOfMintsExceeded(); error MintingPaused(); error InvalidReferral(); error InvalidSignature(); error BalanceEmpty(); error TransferFailed(); error MaxBatchSizeExceeded(); error BurnToMintDisabled(); error NotTokenOwner(); error NotPlatform(); error NotApprovedToTransfer(); error InvalidAmountOfTokens(); error WrongPassword(); error LockedForever(); error URIQueryForNonexistentToken(); error InvalidTokenId(); error NotSupported(); // // STRUCTS // struct Auth { bytes32 key; bytes32[] proof; } struct MintTier { uint16 numMints; uint16 mintDiscount; //BPS } struct Discount { uint16 affiliateDiscount; //BPS MintTier[] mintTiers; } struct Config { string baseUri; address affiliateSigner; address ownerAltPayout; // optional alternative address for owner withdrawals. address superAffiliatePayout; // optional super affiliate address, will receive half of platform fee if set. uint32[] maxSupply; // max supply for each mintable tokenId uint32 maxBatchSize; uint16 affiliateFee; //BPS uint16 platformFee; //BPS uint16 defaultRoyalty; //BPS Discount discounts; } struct Options { bool uriLocked; bool maxSupplyLocked; bool affiliateFeeLocked; bool discountsLocked; bool ownerAltPayoutLocked; bool provenanceHashLocked; } struct DutchInvite { uint128 price; uint128 reservePrice; uint128 delta; uint32 start; uint32 end; uint32 limit; uint32 maxSupply; uint32 interval; uint32 unitSize; // mint 1 get x bool randomize; // true for random tokenId, false for user selected uint32[] tokenIds; // token id mintable from this list address tokenAddress; } struct Invite { uint128 price; uint32 start; uint32 end; uint32 limit; uint32 maxSupply; uint32 unitSize; // mint 1 get x bool randomize; // true for random tokenId, false for user selected uint32[] tokenIds; // token ids mintable from this list address tokenAddress; } struct OwnerBalance { uint128 owner; uint128 platform; } struct ValidationArgs { address owner; address affiliate; uint256[] quantities; uint256[] tokenIds; } // address constant PLATFORM = 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC; // TEST (account[2]) address constant PLATFORM = 0x86B82972282Dd22348374bC63fd21620F7ED847B; uint16 constant MAXBPS = 5000; // max fee or discount is 50% library ArchetypeLogic { // // EVENTS // event Invited(bytes32 indexed key, bytes32 indexed cid); event Referral(address indexed affiliate, address token, uint128 wad, uint256 numMints); event Withdrawal(address indexed src, address token, uint128 wad); // calculate price based on affiliate usage and mint discounts function computePrice( DutchInvite storage invite, Discount storage discounts, uint256 numTokens, bool affiliateUsed ) public view returns (uint256) { uint256 price = invite.price; if (invite.interval != 0) { uint256 diff = (((block.timestamp - invite.start) / invite.interval) * invite.delta); if (price > invite.reservePrice) { if (diff > price - invite.reservePrice) { price = invite.reservePrice; } else { price = price - diff; } } else if (price < invite.reservePrice) { if (diff > invite.reservePrice - price) { price = invite.reservePrice; } else { price = price + diff; } } } uint256 cost = price * numTokens; if (affiliateUsed) { cost = cost - ((cost * discounts.affiliateDiscount) / 10000); } for (uint256 i = 0; i < discounts.mintTiers.length; i++) { if (numTokens >= discounts.mintTiers[i].numMints) { return cost = cost - ((cost * discounts.mintTiers[i].mintDiscount) / 10000); } } return cost; } function validateMint( DutchInvite storage i, Config storage config, Auth calldata auth, mapping(address => mapping(bytes32 => uint256)) storage minted, mapping(bytes32 => uint256) storage listSupply, uint256[] storage tokenSupply, bytes calldata signature, ValidationArgs memory args ) public view { if (args.affiliate != address(0)) { if ( args.affiliate == PLATFORM || args.affiliate == args.owner || args.affiliate == msg.sender ) { revert InvalidReferral(); } validateAffiliate(args.affiliate, signature, config.affiliateSigner); } if (i.limit == 0) { revert MintingPaused(); } if (!verify(auth, i.tokenAddress, msg.sender)) { revert WalletUnauthorizedToMint(); } if (block.timestamp < i.start) { revert MintNotYetStarted(); } if (i.end > i.start && block.timestamp > i.end) { revert MintEnded(); } uint256 totalQuantity = 0; for (uint256 j = 0; j < args.quantities.length; j++) { totalQuantity += args.quantities[j]; } uint256 totalAfterMint; if (i.limit < i.maxSupply) { totalAfterMint = minted[msg.sender][auth.key] + totalQuantity; if (totalAfterMint > i.limit) { revert NumberOfMintsExceeded(); } } if (i.maxSupply < 2**32 - 1) { totalAfterMint = listSupply[auth.key] + totalQuantity; if (totalAfterMint > i.maxSupply) { revert ListMaxSupplyExceeded(); } } uint256[] memory checked = new uint256[](tokenSupply.length); for (uint256 j = 0; j < args.tokenIds.length; j++) { uint256 tokenId = args.tokenIds[j]; if (!i.randomize) { if (i.tokenIds.length != 0) { bool isValid = false; for (uint256 k = 0; k < i.tokenIds.length; k++) { if (tokenId == i.tokenIds[k]) { isValid = true; break; } } if (!isValid) { revert InvalidTokenId(); } } } if ( (tokenSupply[tokenId - 1] + checked[tokenId - 1] + args.quantities[j]) > config.maxSupply[tokenId - 1] ) { revert MaxSupplyExceeded(); } checked[tokenId - 1] += args.quantities[j]; } if (totalQuantity > config.maxBatchSize) { revert MaxBatchSizeExceeded(); } uint256 cost = computePrice(i, config.discounts, totalQuantity, args.affiliate != address(0)); if (i.tokenAddress != address(0)) { IERC20Upgradeable erc20Token = IERC20Upgradeable(i.tokenAddress); if (erc20Token.allowance(msg.sender, address(this)) < cost) { revert NotApprovedToTransfer(); } if (erc20Token.balanceOf(msg.sender) < cost) { revert Erc20BalanceTooLow(); } if (msg.value != 0) { revert ExcessiveEthSent(); } } else { if (msg.value < cost) { revert InsufficientEthSent(); } // if (msg.value > cost) { // revert ExcessiveEthSent(); // } } } function updateBalances( DutchInvite storage i, Config storage config, mapping(address => OwnerBalance) storage _ownerBalance, mapping(address => mapping(address => uint128)) storage _affiliateBalance, address affiliate, uint256 quantity ) public { address tokenAddress = i.tokenAddress; uint128 value = uint128(msg.value); if (tokenAddress != address(0)) { value = uint128(computePrice(i, config.discounts, quantity, affiliate != address(0))); } uint128 affiliateWad = 0; if (affiliate != address(0)) { affiliateWad = (value * config.affiliateFee) / 10000; _affiliateBalance[affiliate][tokenAddress] += affiliateWad; emit Referral(affiliate, tokenAddress, affiliateWad, quantity); } uint128 superAffiliateWad = 0; if (config.superAffiliatePayout != address(0)) { superAffiliateWad = ((value * config.platformFee) / 2) / 10000; _affiliateBalance[config.superAffiliatePayout][tokenAddress] += superAffiliateWad; } OwnerBalance memory balance = _ownerBalance[tokenAddress]; uint128 platformWad = ((value * config.platformFee) / 10000) - superAffiliateWad; uint128 ownerWad = value - affiliateWad - platformWad - superAffiliateWad; _ownerBalance[tokenAddress] = OwnerBalance({ owner: balance.owner + ownerWad, platform: balance.platform + platformWad }); if (tokenAddress != address(0)) { IERC20Upgradeable erc20Token = IERC20Upgradeable(tokenAddress); erc20Token.transferFrom(msg.sender, address(this), value); } } function withdrawTokens( Config storage config, mapping(address => OwnerBalance) storage _ownerBalance, mapping(address => mapping(address => uint128)) storage _affiliateBalance, address owner, address[] calldata tokens ) public { for (uint256 i = 0; i < tokens.length; i++) { address tokenAddress = tokens[i]; uint128 wad = 0; if (msg.sender == owner || msg.sender == config.ownerAltPayout || msg.sender == PLATFORM) { OwnerBalance storage balance = _ownerBalance[tokenAddress]; if (msg.sender == owner || msg.sender == config.ownerAltPayout) { wad = balance.owner; balance.owner = 0; } else { wad = balance.platform; balance.platform = 0; } } else { wad = _affiliateBalance[msg.sender][tokenAddress]; _affiliateBalance[msg.sender][tokenAddress] = 0; } if (wad == 0) { revert BalanceEmpty(); } if (tokenAddress == address(0)) { bool success = false; // send to ownerAltPayout if set and owner is withdrawing if (msg.sender == owner && config.ownerAltPayout != address(0)) { (success, ) = payable(config.ownerAltPayout).call{ value: wad }(""); } else { (success, ) = msg.sender.call{ value: wad }(""); } if (!success) { revert TransferFailed(); } } else { IERC20Upgradeable erc20Token = IERC20Upgradeable(tokenAddress); if (msg.sender == owner && config.ownerAltPayout != address(0)) { erc20Token.transfer(config.ownerAltPayout, wad); } else { erc20Token.transfer(msg.sender, wad); } } emit Withdrawal(msg.sender, tokenAddress, wad); } } function validateAffiliate( address affiliate, bytes calldata signature, address affiliateSigner ) public view { bytes32 signedMessagehash = ECDSA.toEthSignedMessageHash( keccak256(abi.encodePacked(affiliate)) ); address signer = ECDSA.recover(signedMessagehash, signature); if (signer != affiliateSigner) { revert InvalidSignature(); } } function verify( Auth calldata auth, address tokenAddress, address account ) public pure returns (bool) { // keys 0-255 and tokenAddress are public if (uint256(auth.key) <= 0xff || auth.key == keccak256(abi.encodePacked(tokenAddress))) { return true; } return MerkleProofLib.verify(auth.proof, auth.key, keccak256(abi.encodePacked(account))); } function getRandomTokenIds( uint256[] memory tokenSupply, uint32[] memory maxSupply, uint32[] memory validIds, uint256 quantity, uint256 seed ) public pure returns (uint256[] memory) { uint256 tokenIdsAvailable = 0; if (validIds.length > 0) { for (uint256 i = 0; i < validIds.length; i++) { tokenIdsAvailable += maxSupply[validIds[i] - 1] - tokenSupply[validIds[i] - 1]; } } else { for (uint256 i = 0; i < maxSupply.length; i++) { tokenIdsAvailable += maxSupply[i] - tokenSupply[i]; } } uint256[] memory tokenIds = new uint256[](quantity); for (uint256 i = 0; i < quantity; i++) { if (tokenIdsAvailable == 0) { revert MaxSupplyExceeded(); } uint256 rand = uint256(keccak256(abi.encode(seed, i))); uint256 num = (rand % tokenIdsAvailable) + 1; if (validIds.length > 0) { for (uint256 j = 0; j < validIds.length; j++) { uint256 available = maxSupply[validIds[j] - 1] - tokenSupply[validIds[j] - 1]; if (num <= available) { tokenIds[i] = validIds[j]; tokenSupply[validIds[j] - 1] += 1; tokenIdsAvailable -= 1; break; } num -= available; } } else { for (uint256 j = 0; j < maxSupply.length; j++) { uint256 available = maxSupply[j] - tokenSupply[j]; if (num <= available) { tokenIds[i] = j + 1; tokenSupply[j] += 1; tokenIdsAvailable -= 1; break; } num -= available; } } } return tokenIds; } function random() public view returns (uint256) { uint256 randomHash = uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp))); return randomHash; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) library ECDSA { function recover(bytes32 hash, bytes calldata signature) internal view returns (address result) { assembly { if eq(signature.length, 65) { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // Directly copy `r` and `s` from the calldata. calldatacopy(0x40, signature.offset, 0x40) // If `s` in lower half order, such that the signature is not malleable. // prettier-ignore if iszero(gt(mload(0x60), 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0)) { mstore(0x00, hash) // Compute `v` and store it in the scratch space. mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(sub(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } } function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal view returns (address result) { assembly { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // prettier-ignore let s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) // If `s` in lower half order, such that the signature is not malleable. // prettier-ignore if iszero(gt(s, 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0)) { mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(sub(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { assembly { // Store into scratch space for keccak256. mstore(0x20, hash) mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 0x40 - 0x04 = 0x3c result := keccak256(0x04, 0x3c) } } function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { assembly { // We need at most 128 bytes for Ethereum signed message header. // The max length of the ASCII reprenstation of a uint256 is 78 bytes. // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a). // The next multiple of 32 above 78 + 26 is 128 (i.e. 0x80). // Instead of allocating, we temporarily copy the 128 bytes before the // start of `s` data to some variables. let m3 := mload(sub(s, 0x60)) let m2 := mload(sub(s, 0x40)) let m1 := mload(sub(s, 0x20)) // The length of `s` is in bytes. let sLength := mload(s) let ptr := add(s, 0x20) // `end` marks the end of the memory which we will compute the keccak256 of. let end := add(ptr, sLength) // Convert the length of the bytes to ASCII decimal representation // and store it into the memory. // prettier-ignore for { let temp := sLength } 1 {} { ptr := sub(ptr, 1) mstore8(ptr, add(48, mod(temp, 10))) temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } // Copy the header over to the memory. mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n") // Compute the keccak256 of the memory. result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a))) // Restore the previous memory. mstore(s, sLength) mstore(sub(s, 0x20), m1) mstore(sub(s, 0x40), m2) mstore(sub(s, 0x60), m3) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error HexLengthInsufficient(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toString(uint256 value) internal pure returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) { assembly { let start := mload(0x40) // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. let m := add(start, and(add(shl(1, length), 0x62), not(0x1f))) // Allocate the memory. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for {} 1 {} { str := sub(str, 2) mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) length := sub(length, 1) // prettier-ignore if iszero(length) { break } } if temp { // Store the function selector of `HexLengthInsufficient()`. mstore(0x00, 0x2194895a) // Revert with (offset, size). revert(0x1c, 0x04) } // Compute the string's length. let strLength := add(sub(end, str), 2) // Move the pointer and write the "0x" prefix. str := sub(str, 0x20) mstore(str, 0x3078) // Move the pointer and write the length. str := sub(str, 2) mstore(str, strLength) } } function toHexString(uint256 value) internal pure returns (string memory str) { assembly { let start := mload(0x40) // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. let m := add(start, 0xa0) // Allocate the memory. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 2) mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) // prettier-ignore if iszero(temp) { break } } // Compute the string's length. let strLength := add(sub(end, str), 2) // Move the pointer and write the "0x" prefix. str := sub(str, 0x20) mstore(str, 0x3078) // Move the pointer and write the length. str := sub(str, 2) mstore(str, strLength) } } function toHexString(address value) internal pure returns (string memory str) { assembly { let start := mload(0x40) // We need 0x20 bytes for the length, 0x02 bytes for the prefix, // and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x02 + 0x28) is 0x60. str := add(start, 0x60) // Allocate the memory. mstore(0x40, str) // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let length := 20 // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 2) mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) length := sub(length, 1) // prettier-ignore if iszero(length) { break } } // Move the pointer and write the "0x" prefix. str := sub(str, 32) mstore(str, 0x3078) // Move the pointer and write the length. str := sub(str, 2) mstore(str, 42) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OTHER STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function replace( string memory subject, string memory search, string memory replacement ) internal pure returns (string memory result) { assembly { let subjectLength := mload(subject) let searchLength := mload(search) let replacementLength := mload(replacement) subject := add(subject, 0x20) search := add(search, 0x20) replacement := add(replacement, 0x20) result := add(mload(0x40), 0x20) let subjectEnd := add(subject, subjectLength) if iszero(gt(searchLength, subjectLength)) { let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1) let h := 0 if iszero(lt(searchLength, 32)) { h := keccak256(search, searchLength) } let m := shl(3, sub(32, and(searchLength, 31))) let s := mload(search) // prettier-ignore for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) // prettier-ignore if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. // prettier-ignore for { let o := 0 } 1 {} { mstore(add(result, o), mload(add(replacement, o))) o := add(o, 0x20) // prettier-ignore if iszero(lt(o, replacementLength)) { break } } result := add(result, replacementLength) subject := add(subject, searchLength) if iszero(searchLength) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) } // prettier-ignore if iszero(lt(subject, subjectSearchEnd)) { break } continue } mstore(result, t) result := add(result, 1) subject := add(subject, 1) // prettier-ignore if iszero(lt(subject, subjectSearchEnd)) { break } } } let resultRemainder := result result := add(mload(0x40), 0x20) let k := add(sub(resultRemainder, result), sub(subjectEnd, subject)) // Copy the rest of the string one word at a time. // prettier-ignore for {} lt(subject, subjectEnd) {} { mstore(resultRemainder, mload(subject)) resultRemainder := add(resultRemainder, 0x20) subject := add(subject, 0x20) } // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(k, 0x40), not(0x1f)))) result := sub(result, 0x20) mstore(result, k) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProofLib { function verify( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool isValid) { assembly { if proof.length { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(proof.offset, shl(5, proof.length)) // Initialize `offset` to the offset of `proof` in the calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. // prettier-ignore for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), calldataload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) // prettier-ignore if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } function verifyMultiProof( bytes32[] calldata proof, bytes32 root, bytes32[] calldata leafs, bool[] calldata flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leafs` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). assembly { // If the number of flags is correct. // prettier-ignore for {} eq(add(leafs.length, proof.length), add(flags.length, 1)) {} { // Left shift by 5 is equivalent to multiplying by 0x20. // Compute the end calldata offset of `leafs`. let leafsEnd := add(leafs.offset, shl(5, leafs.length)) // These are the calldata offsets. let leafsOffset := leafs.offset let flagsOffset := flags.offset let proofOffset := proof.offset // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) let hashesBack := hashesFront // This is the end of the memory for the queue. let end := add(hashesBack, shl(5, flags.length)) // For the case where `proof.length + leafs.length == 1`. if iszero(flags.length) { // If `proof.length` is zero, `leafs.length` is 1. if iszero(proof.length) { isValid := eq(calldataload(leafsOffset), root) break } // If `leafs.length` is zero, `proof.length` is 1. if iszero(leafs.length) { isValid := eq(calldataload(proofOffset), root) break } } // prettier-ignore for {} 1 {} { let a := 0 // Pops a value from the queue into `a`. switch lt(leafsOffset, leafsEnd) case 0 { // Pop from `hashes` if there are no more leafs. a := mload(hashesFront) hashesFront := add(hashesFront, 0x20) } default { // Otherwise, pop from `leafs`. a := calldataload(leafsOffset) leafsOffset := add(leafsOffset, 0x20) } let b := 0 // If the flag is false, load the next proof, // else, pops from the queue. switch calldataload(flagsOffset) case 0 { // Loads the next proof. b := calldataload(proofOffset) proofOffset := add(proofOffset, 0x20) } default { // Pops a value from the queue into `a`. switch lt(leafsOffset, leafsEnd) case 0 { // Pop from `hashes` if there are no more leafs. b := mload(hashesFront) hashesFront := add(hashesFront, 0x20) } default { // Otherwise, pop from `leafs`. b := calldataload(leafsOffset) leafsOffset := add(leafsOffset, 0x20) } } // Advance to the next flag offset. flagsOffset := add(flagsOffset, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) // prettier-ignore if iszero(lt(hashesBack, end)) { break } } // Checks if the last value in the queue is same as the root. isValid := eq(mload(sub(hashesBack, 0x20)), root) break } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/ArchetypeLogic.sol": { "ArchetypeLogic": "0xaccc072242b2b8bc0b7ba9abeb6b5192fe533304" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"InvalidConfig","type":"error"},{"inputs":[],"name":"LockedForever","type":"error"},{"inputs":[],"name":"MaxSupplyExceeded","type":"error"},{"inputs":[],"name":"NotPlatform","type":"error"},{"inputs":[],"name":"NotSupported","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"WrongPassword","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","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":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"key","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"cid","type":"bytes32"}],"name":"Invited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"affiliate","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint128","name":"wad","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"numMints","type":"uint256"}],"name":"Referral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint128","name":"wad","type":"uint128"}],"name":"Withdrawal","type":"event"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"}],"name":"affiliateBalance","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"affiliateBalanceToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct Auth","name":"auth","type":"tuple"},{"internalType":"address[]","name":"toList","type":"address[]"},{"internalType":"uint256[]","name":"quantityList","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"batchMintTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"string","name":"baseUri","type":"string"},{"internalType":"address","name":"affiliateSigner","type":"address"},{"internalType":"address","name":"ownerAltPayout","type":"address"},{"internalType":"address","name":"superAffiliatePayout","type":"address"},{"internalType":"uint32","name":"maxBatchSize","type":"uint32"},{"internalType":"uint16","name":"affiliateFee","type":"uint16"},{"internalType":"uint16","name":"platformFee","type":"uint16"},{"internalType":"uint16","name":"defaultRoyalty","type":"uint16"},{"components":[{"internalType":"uint16","name":"affiliateDiscount","type":"uint16"},{"components":[{"internalType":"uint16","name":"numMints","type":"uint16"},{"internalType":"uint16","name":"mintDiscount","type":"uint16"}],"internalType":"struct MintTier[]","name":"mintTiers","type":"tuple[]"}],"internalType":"struct Discount","name":"discounts","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"components":[{"internalType":"string","name":"baseUri","type":"string"},{"internalType":"address","name":"affiliateSigner","type":"address"},{"internalType":"address","name":"ownerAltPayout","type":"address"},{"internalType":"address","name":"superAffiliatePayout","type":"address"},{"internalType":"uint32[]","name":"maxSupply","type":"uint32[]"},{"internalType":"uint32","name":"maxBatchSize","type":"uint32"},{"internalType":"uint16","name":"affiliateFee","type":"uint16"},{"internalType":"uint16","name":"platformFee","type":"uint16"},{"internalType":"uint16","name":"defaultRoyalty","type":"uint16"},{"components":[{"internalType":"uint16","name":"affiliateDiscount","type":"uint16"},{"components":[{"internalType":"uint16","name":"numMints","type":"uint16"},{"internalType":"uint16","name":"mintDiscount","type":"uint16"}],"internalType":"struct MintTier[]","name":"mintTiers","type":"tuple[]"}],"internalType":"struct Discount","name":"discounts","type":"tuple"}],"internalType":"struct Config","name":"config_","type":"tuple"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"invites","outputs":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"},{"internalType":"uint128","name":"delta","type":"uint128"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"uint32","name":"limit","type":"uint32"},{"internalType":"uint32","name":"maxSupply","type":"uint32"},{"internalType":"uint32","name":"interval","type":"uint32"},{"internalType":"uint32","name":"unitSize","type":"uint32"},{"internalType":"bool","name":"randomize","type":"bool"},{"internalType":"address","name":"tokenAddress","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":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"listSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockDiscounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockOwnerAltPayout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockProvenanceHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct Auth","name":"auth","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct Auth","name":"auth","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mintTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct Auth","name":"auth","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mintToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct Auth[]","name":"auth","type":"tuple[]"},{"internalType":"uint256[]","name":"quantity","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenId","type":"uint256[]"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mintTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"minted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"options","outputs":[{"internalType":"bool","name":"uriLocked","type":"bool"},{"internalType":"bool","name":"maxSupplyLocked","type":"bool"},{"internalType":"bool","name":"affiliateFeeLocked","type":"bool"},{"internalType":"bool","name":"discountsLocked","type":"bool"},{"internalType":"bool","name":"ownerAltPayoutLocked","type":"bool"},{"internalType":"bool","name":"provenanceHashLocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerBalance","outputs":[{"components":[{"internalType":"uint128","name":"owner","type":"uint128"},{"internalType":"uint128","name":"platform","type":"uint128"}],"internalType":"struct OwnerBalance","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"ownerBalanceToken","outputs":[{"components":[{"internalType":"uint128","name":"owner","type":"uint128"},{"internalType":"uint128","name":"platform","type":"uint128"}],"internalType":"struct OwnerBalance","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platform","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"provenance","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"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":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"affiliateFee","type":"uint16"}],"name":"setAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseUri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint16","name":"feeNumerator","type":"uint16"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"affiliateDiscount","type":"uint16"},{"components":[{"internalType":"uint16","name":"numMints","type":"uint16"},{"internalType":"uint16","name":"mintDiscount","type":"uint16"}],"internalType":"struct MintTier[]","name":"mintTiers","type":"tuple[]"}],"internalType":"struct Discount","name":"discounts","type":"tuple"}],"name":"setDiscounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"},{"internalType":"bytes32","name":"_cid","type":"bytes32"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"},{"internalType":"uint128","name":"delta","type":"uint128"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"uint32","name":"limit","type":"uint32"},{"internalType":"uint32","name":"maxSupply","type":"uint32"},{"internalType":"uint32","name":"interval","type":"uint32"},{"internalType":"uint32","name":"unitSize","type":"uint32"},{"internalType":"bool","name":"randomize","type":"bool"},{"internalType":"uint32[]","name":"tokenIds","type":"uint32[]"},{"internalType":"address","name":"tokenAddress","type":"address"}],"internalType":"struct DutchInvite","name":"_dutchInvite","type":"tuple"}],"name":"setDutchInvite","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"},{"internalType":"bytes32","name":"_cid","type":"bytes32"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"uint32","name":"limit","type":"uint32"},{"internalType":"uint32","name":"maxSupply","type":"uint32"},{"internalType":"uint32","name":"unitSize","type":"uint32"},{"internalType":"bool","name":"randomize","type":"bool"},{"internalType":"uint32[]","name":"tokenIds","type":"uint32[]"},{"internalType":"address","name":"tokenAddress","type":"address"}],"internalType":"struct Invite","name":"_invite","type":"tuple"}],"name":"setInvite","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"maxBatchSize","type":"uint32"}],"name":"setMaxBatchSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"newMaxSupply","type":"uint32[]"},{"internalType":"string","name":"password","type":"string"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ownerAltPayout","type":"address"}],"name":"setOwnerAltPayout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"provenanceHash","type":"string"}],"name":"setProvenanceHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"superAffiliatePayout","type":"address"}],"name":"setSuperAffiliatePayout","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":"tokenId","type":"uint256"}],"name":"tokenSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50615db180620000216000396000f3fe6080604052600436106103195760003560e01c806355f804b3116101ab578063a3edb86a116100f7578063d71d8d2311610095578063ead005531161006f578063ead0055314610bd7578063f242432a14610bf7578063f2fde38b14610c17578063fd614f2a14610c3757600080fd5b8063d71d8d2314610b4e578063de6cd0db14610b6e578063e985e9c514610b8e57600080fd5b8063bedcf003116100d1578063bedcf00314610a7a578063c7494df714610aec578063ce216e2f14610b0c578063d5abeb0114610b2c57600080fd5b8063a3edb86a14610958578063a5aa4aa41461099b578063b2938bd414610a5a57600080fd5b80637ded184811610164578063978a45091161013e578063978a4509146108a15780639a7a973c146108eb578063a15947c414610918578063a22cb4651461093857600080fd5b80637ded18481461085b5780638da5cb5b1461086e57806395d89b411461088c57600080fd5b806355f804b31461079c5780635ecb16cd146107bc5780636f33659f146107dc578063715018a6146107fc57806379502c55146108115780637c5d0a081461083b57600080fd5b80632a55205a1161026a5780634331f639116102235780634a21a2df116101fd5780634a21a2df1461070e5780634bde38c8146107215780634e1273f41461075c5780635000d3d11461078957600080fd5b80634331f639146106ae57806343a11bc9146106ce57806347286bc0146106ee57600080fd5b80632a55205a146105e75780632eb2c2d61461062657806331e1fdac1461064657806332f7c6d4146106665780633a24417a146106865780633ccfd60b1461069957600080fd5b80631069143a116102d75780631fff79b0116102b15780631fff79b0146104b557806321d5bf24146104c85780632693ebf21461052f57806327a594371461054f57600080fd5b80631069143a146103fa578063109695231461048057806318160ddd146104a057600080fd5b8062fdd58e1461031e57806301ffc9a71461035157806306fdde03146103815780630c6f910b146103a35780630e89341c146103c55780630f7309e8146103e5575b600080fd5b34801561032a57600080fd5b5061033e6103393660046142bf565b610c57565b6040519081526020015b60405180910390f35b34801561035d57600080fd5b5061037161036c36600461473e565b610cef565b6040519015158152602001610348565b34801561038d57600080fd5b50610396610d0f565b604051610348919061506c565b3480156103af57600080fd5b506103c36103be366004614b3d565b610d9e565b005b3480156103d157600080fd5b506103966103e0366004614592565b610e1c565b3480156103f157600080fd5b50610396610ea1565b34801561040657600080fd5b50610109546104479060ff80821691610100810482169162010000820481169163010000008104821691600160201b82048116916501000000000090041686565b604080519615158752941515602087015292151593850193909352151560608401529015156080830152151560a082015260c001610348565b34801561048c57600080fd5b506103c361049b366004614776565b610eaf565b3480156104ac57600080fd5b5061033e610efd565b6103c36104c3366004614a63565b610f5f565b3480156104d457600080fd5b506105176104e3366004614144565b6001600160a01b03918216600090815260ff602090815260408083209390941682529190915220546001600160801b031690565b6040516001600160801b039091168152602001610348565b34801561053b57600080fd5b5061033e61054a366004614592565b610f76565b34801561055b57600080fd5b506105c061056a366004614121565b6040805180820190915260008082526020820152506001600160a01b0316600090815260fe60209081526040918290208251808401909352546001600160801b038082168452600160801b909104169082015290565b6040805182516001600160801b039081168252602093840151169281019290925201610348565b3480156105f357600080fd5b50610607610602366004614b71565b610fdc565b604080516001600160a01b039093168352602083019190915201610348565b34801561063257600080fd5b506103c361064136600461417c565b61108a565b34801561065257600080fd5b506103c36106613660046147a8565b6110d6565b34801561067257600080fd5b506103c3610681366004614776565b611557565b6103c36106943660046143b1565b6115e1565b3480156106a557600080fd5b506103c3611696565b3480156106ba57600080fd5b506103c36106c93660046142ea565b611707565b3480156106da57600080fd5b506103c36106e93660046146ea565b61173b565b3480156106fa57600080fd5b506103c36107093660046145aa565b611a24565b6103c361071c36600461493b565b611b75565b34801561072d57600080fd5b507386b82972282dd22348374bc63fd21620f7ed847b5b6040516001600160a01b039091168152602001610348565b34801561076857600080fd5b5061077c610777366004614351565b611b85565b6040516103489190614f6e565b6103c3610797366004614843565b611ce6565b3480156107a857600080fd5b506103c36107b7366004614776565b6121b1565b3480156107c857600080fd5b506103c36107d7366004614317565b6121f2565b3480156107e857600080fd5b506103c36107f7366004614b92565b612272565b34801561080857600080fd5b506103c3612297565b34801561081d57600080fd5b506108266122ab565b6040516103489998979695949392919061507f565b34801561084757600080fd5b506103c3610856366004614776565b61241b565b6103c36108693660046149c0565b6124a0565b34801561087a57600080fd5b506097546001600160a01b0316610744565b34801561089857600080fd5b50610396612aa7565b3480156108ad57600080fd5b506105176108bc366004614121565b6001600160a01b0316600090815260ff602090815260408083208380529091529020546001600160801b031690565b3480156108f757600080fd5b5061033e610906366004614592565b600090815260fd602052604090205490565b34801561092457600080fd5b506103c3610933366004614776565b612ab5565b34801561094457600080fd5b506103c361095336600461428b565b612b42565b34801561096457600080fd5b5061033e6109733660046142bf565b6001600160a01b0391909116600090815260fc60209081526040808320938352929052205490565b3480156109a757600080fd5b50610a436109b6366004614592565b60fb6020526000908152604090208054600182015460028301546004909301546001600160801b0380841694600160801b948590048216949184169391820463ffffffff90811693600160a01b8404821693600160c01b8104831693600160e01b90910483169280821692600160201b830490911691600160401b900460ff16906001600160a01b03168b565b6040516103489b9a9998979695949392919061541a565b348015610a6657600080fd5b506103c3610a75366004614522565b612b4d565b348015610a8657600080fd5b5060408051808201825260008082526020918201819052805260fe815281518083019092527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af546001600160801b038082168452600160801b90910416908201526105c0565b348015610af857600080fd5b506103c3610b07366004614776565b612cf1565b348015610b1857600080fd5b506103c3610b27366004614776565b612d7a565b348015610b3857600080fd5b50610b41612e01565b6040516103489190615022565b348015610b5a57600080fd5b506103c3610b69366004614121565b612e89565b348015610b7a57600080fd5b506103c3610b89366004614776565b612ee0565b348015610b9a57600080fd5b50610371610ba9366004614144565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b348015610be357600080fd5b506103c3610bf2366004614121565b612f63565b348015610c0357600080fd5b506103c3610c12366004614225565b612fba565b348015610c2357600080fd5b506103c3610c32366004614121565b612fff565b348015610c4357600080fd5b506103c3610c52366004614af1565b613075565b60006001600160a01b038316610cc75760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060009081526065602090815260408083206001600160a01b03949094168352929052205490565b6000610cfa8261321b565b80610d095750610d098261326b565b92915050565b61010a8054610d1d9061592a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d499061592a565b8015610d965780601f10610d6b57610100808354040283529160200191610d96565b820191906000526020600020905b815481529060010190602001808311610d7957829003601f168201915b505050505081565b610da6613290565b6101095462010000900460ff1615610dd15760405163249fab5d60e01b815260040160405180910390fd5b61138861ffff82161115610df8576040516306b7c75960e31b815260040160405180910390fd5b610106805461ffff909216600160201b0265ffff0000000019909216919091179055565b6060610e27826132ea565b610e4457604051630a14c4b560e41b815260040160405180910390fd5b6101018054610e529061592a565b15159050610e6f5760405180602001604052806000815250610d09565b610101610e7b83613300565b604051602001610e8c929190614e38565b60405160208183030381529060405292915050565b61010c8054610d1d9061592a565b610eb7613290565b6101095465010000000000900460ff1615610ee55760405163249fab5d60e01b815260040160405180910390fd5b8051610ef99061010c906020840190613d12565b5050565b600080805b61010054811015610f59576101008181548110610f2f57634e487b7160e01b600052603260045260246000fd5b906000526020600020015482610f4591906155c1565b915080610f518161598b565b915050610f02565b50919050565b610f6e868633878787876124a0565b505050505050565b6000610f81826132ea565b610f9e57604051630a14c4b560e41b815260040160405180910390fd5b610100610fac600184615618565b81548110610fca57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b600082815260ca602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161105157506040805180820190915260c9546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090611070906001600160601b0316876155f9565b61107a91906155d9565b91519350909150505b9250929050565b6001600160a01b0385163314806110a657506110a68533610ba9565b6110c25760405162461bcd60e51b8152600401610cbe906151a0565b6110cf858585858561334e565b5050505050565b600054610100900460ff16158080156110f65750600054600160ff909116105b806111105750303b158015611110575060005460ff166001145b6111735760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610cbe565b6000805460ff191660011790558015611196576000805461ff0019166101001790555b84516111aa9061010a906020880190613d12565b5083516111bf9061010b906020870190613d12565b506111d860405180602001604052806000815250613542565b6113886111eb60e0850160c08601614b3d565b61ffff161180611210575061138861120a610100850160e08601614b3d565b61ffff16115b8061123057506101f461122a610100850160e08601614b3d565b61ffff16105b8061125b5750611388611247610120850185615560565b611255906020810190614b3d565b61ffff16115b8061127e575060006112736040850160208601614121565b6001600160a01b0316145b8061129c575061129460c0840160a08501614b92565b63ffffffff16155b156112ba576040516306b7c75960e31b815260040160405180910390fd5b60015b6112cb610120850185615560565b6112d990602081019061548e565b9050811015611426576113886112f3610120860186615560565b61130190602081019061548e565b8381811061131f57634e487b7160e01b600052603260045260246000fd5b90506040020160200160208101906113379190614b3d565b61ffff1611806113f65750611350610120850185615560565b61135e90602081019061548e565b611369600184615618565b81811061138657634e487b7160e01b600052603260045260246000fd5b61139c9260206040909202019081019150614b3d565b61ffff166113ae610120860186615560565b6113bc90602081019061548e565b838181106113da57634e487b7160e01b600052603260045260246000fd5b6113f09260206040909202019081019150614b3d565b61ffff16115b15611414576040516306b7c75960e31b815260040160405180910390fd5b8061141e8161598b565b9150506112bd565b50826101016114358282615aba565b50611445905060808401846154d5565b90506001600160401b0381111561146c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611495578160200160208202803683370190505b5080516114ab9161010091602090910190613d96565b506114b4613572565b610103546001600160a01b0316156114f15761010354610106546114ec916001600160a01b031690600160401b900461ffff16611707565b61150b565b6101065461150b908390600160401b900461ffff16611707565b80156110cf576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b61155f613290565b60405160200161156e90614eb8565b60405160208183030381529060405280519060200120816040516020016115959190614e1c565b60405160208183030381529060405280519060200120146115c957604051635ee88f9760e01b815260040160405180910390fd5b50610109805464ff000000001916600160201b179055565b60005b8881101561168a576116788a8a8381811061160f57634e487b7160e01b600052603260045260246000fd5b90506020028101906116219190615560565b89898481811061164157634e487b7160e01b600052603260045260246000fd5b905060200201353389898681811061166957634e487b7160e01b600052603260045260246000fd5b905060200201358888886124a0565b806116828161598b565b9150506115e4565b50505050505050505050565b604080516001808252818301909252600091602080830190803683370190505090506000816000815181106116db57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050611704816121f2565b50565b61170f613290565b610106805461ffff60401b1916600160401b61ffff841690810291909117909155610ef99083906135a1565b611743613290565b6040805161018081019091528061175d6020840184614b23565b6001600160801b0316815260209081019061177a90840184614b23565b6001600160801b0316815260200160006001600160801b031681526020018260200160208101906117ab9190614b92565b63ffffffff1681526020016117c66060840160408501614b92565b63ffffffff1681526020016117e16080840160608501614b92565b63ffffffff1681526020016117fc60a0840160808501614b92565b63ffffffff1681526000602082015260400161181e60c0840160a08501614b92565b63ffffffff16815260200161183960e0840160c08501614578565b1515815260200161184d60e08401846154d5565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161189661012084016101008501614121565b6001600160a01b03169052600084815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b911515919091021790925561014083015180516119c79260038501920190613dd0565b506101609190910151600490910180546001600160a01b0319166001600160a01b03909216919091179055604051829084907fe9a0c17645ed78ccc9996259f00297ffc75e6b9d22cd605ccc9992cc8ca3f4c190600090a3505050565b611a2c613290565b42816060015163ffffffff161015611a4b5763ffffffff421660608201525b600083815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b911515919091021790925561014083015180518493926119c7926003850192910190613dd0565b6110cf85853360008787876124a0565b60608151835114611bea5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610cbe565b600083516001600160401b03811115611c1357634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611c3c578160200160208202803683370190505b50905060005b8451811015611cde57611ca3858281518110611c6e57634e487b7160e01b600052603260045260246000fd5b6020026020010151858381518110611c9657634e487b7160e01b600052603260045260246000fd5b6020026020010151610c57565b828281518110611cc357634e487b7160e01b600052603260045260246000fd5b6020908102919091010152611cd78161598b565b9050611c42565b509392505050565b8588141580611cf55750858414155b15611d13576040516306b7c75960e31b815260040160405180910390fd5b8935600090815260fb602052604090206002810154600160401b900460ff1680611d4f575060028101546001600160201b90910463ffffffff16115b15611d6d57604051630280e1e560e61b815260040160405180910390fd5b60408051608081018252600080825260208201526060918101829052818101919091526040518060800160405280611dad6097546001600160a01b031690565b6001600160a01b03168152602001866001600160a01b031681526020018a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208a810282810182019093528a82529283019290918b918b918291850190849080828437600081840152601f19601f82011690508083019250505050505050815250905073accc072242b2b8bc0b7ba9abeb6b5192fe533304630e3deb14836101018f60fc60fd6101008b8b8a6040518a63ffffffff1660e01b8152600401611e9699989796959493929190615336565b60006040518083038186803b158015611eae57600080fd5b505af4158015611ec2573d6000803e3d6000fd5b5050505060005b8a81101561200d576060611f5f8d8d84818110611ef657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611f0b9190614121565b8a8a85818110611f2b57634e487b7160e01b600052603260045260246000fd5b905060200201358d8d86818110611f5257634e487b7160e01b600052603260045260246000fd5b905060200201358461369e565b8a8a83818110611f7f57634e487b7160e01b600052603260045260246000fd5b9050602002013561010060018b8b86818110611fab57634e487b7160e01b600052603260045260246000fd5b90506020020135611fbc9190615618565b81548110611fda57634e487b7160e01b600052603260045260246000fd5b906000526020600020016000828254611ff391906155c1565b9091555082915061200590508161598b565b915050611ec9565b506000805b89811015612060578a8a8281811061203a57634e487b7160e01b600052603260045260246000fd5b905060200201358261204c91906155c1565b9150806120588161598b565b915050612012565b50600183015463ffffffff600160e01b82048116600160c01b9092041610156120d3578060fc6000336001600160a01b03166001600160a01b0316815260200190815260200160002060008f60000135815260200190815260200160002060008282546120cd91906155c1565b90915550505b600183015463ffffffff600160e01b90910481161015612113578c35600090815260fd60205260408120805483929061210d9084906155c1565b90915550505b6040516329ba982960e21b815260048101849052610101602482015260fe604482015260ff60648201526001600160a01b038716608482015260a4810182905273accc072242b2b8bc0b7ba9abeb6b5192fe5333049063a6ea60a49060c40160006040518083038186803b15801561218a57600080fd5b505af415801561219e573d6000803e3d6000fd5b5050505050505050505050505050505050565b6121b9613290565b6101095460ff16156121de5760405163249fab5d60e01b815260040160405180910390fd5b8051610ef990610101906020840190613d12565b73accc072242b2b8bc0b7ba9abeb6b5192fe5333046360f0e59661010160fe60ff6122256097546001600160a01b031690565b866040518663ffffffff1660e01b81526004016122469594939291906152c8565b60006040518083038186803b15801561225e57600080fd5b505af41580156110cf573d6000803e3d6000fd5b61227a613290565b610106805463ffffffff191663ffffffff92909216919091179055565b61229f613290565b6122a960006137b4565b565b610101805481906122bb9061592a565b80601f01602080910402602001604051908101604052809291908181526020018280546122e79061592a565b80156123345780601f1061230957610100808354040283529160200191612334565b820191906000526020600020905b81548152906001019060200180831161231757829003601f168201915b505050600184015460028501546003860154600587015460408051808201825260068a01805461ffff908116835260078c01805485516020828102820181019097528181529c9d6001600160a01b039a8b169d998b169c5097909916995063ffffffff861698600160201b870483169866010000000000008804841698600160401b90980490931696958086019392919060009084015b8282101561240e576000848152602090819020604080518082019091529084015461ffff80821683526201000090910416818301528252600190920191016123cb565b5050505081525050905089565b612423613290565b60405160200161243290614eb8565b60405160208183030381529060405280519060200120816040516020016124599190614e1c565b604051602081830303815290604052805190602001201461248d57604051635ee88f9760e01b815260040160405180910390fd5b50610109805461ff001916610100179055565b8635600090815260fb6020526040902060028101546001600160201b90910463ffffffff1611156124ea5760028101546124e790600160201b900463ffffffff16886155f9565b96505b604080516080810182526000808252602082015260609181018290528181019190915260028201546060908190600160401b900460ff16156126ea57600073accc072242b2b8bc0b7ba9abeb6b5192fe533304635ec01e4d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561256c57600080fd5b505af4158015612580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a49190614b59565b905073accc072242b2b8bc0b7ba9abeb6b5192fe5333046310f11a15610100610101600401886003018f866040518663ffffffff1660e01b81526004016125ef959493929190614fa6565b60006040518083038186803b15801561260757600080fd5b505af415801561261b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126439190810190614486565b925082516001600160401b0381111561266c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612695578160200160208202803683370190505b50915060005b83518110156126e35760018382815181106126c657634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806126db8161598b565b91505061269b565b5050612788565b6040805160018082528183019092529060208083019080368337019050509150878260008151811061272c57634e487b7160e01b600052603260045260246000fd5b602090810291909101015260408051600180825281830190925290816020016020820280368337019050509050898160008151811061277b57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60405180608001604052806127a56097546001600160a01b031690565b6001600160a01b03168152602001886001600160a01b03168152602001828152602001838152509250505073accc072242b2b8bc0b7ba9abeb6b5192fe533304630e3deb14836101018c60fc60fd6101008b8b8a6040518a63ffffffff1660e01b815260040161281d99989796959493929190615336565b60006040518083038186803b15801561283557600080fd5b505af4158015612849573d6000803e3d6000fd5b5050505060005b8160600151518110156129795760606128c1898460600151848151811061288757634e487b7160e01b600052603260045260246000fd5b6020026020010151856040015185815181106128b357634e487b7160e01b600052603260045260246000fd5b60200260200101518461369e565b826040015182815181106128e557634e487b7160e01b600052603260045260246000fd5b602002602001015161010060018560600151858151811061291657634e487b7160e01b600052603260045260246000fd5b60200260200101516129289190615618565b8154811061294657634e487b7160e01b600052603260045260246000fd5b90600052602060002001600082825461295f91906155c1565b9091555082915061297190508161598b565b915050612850565b50600182015463ffffffff600160e01b82048116600160c01b9092041610156129cd5733600090815260fc602090815260408083208c358452909152812080548a92906129c79084906155c1565b90915550505b600182015463ffffffff600160e01b90910481161015612a0d578835600090815260fd6020526040812080548a9290612a079084906155c1565b90915550505b6040516329ba982960e21b815260048101839052610101602482015260fe604482015260ff60648201526001600160a01b038616608482015260a4810189905273accc072242b2b8bc0b7ba9abeb6b5192fe5333049063a6ea60a49060c40160006040518083038186803b158015612a8457600080fd5b505af4158015612a98573d6000803e3d6000fd5b50505050505050505050505050565b61010b8054610d1d9061592a565b612abd613290565b604051602001612acc90614eb8565b6040516020818303038152906040528051906020012081604051602001612af39190614e1c565b6040516020818303038152906040528051906020012014612b2757604051635ee88f9760e01b815260040160405180910390fd5b50610109805465ff0000000000191665010000000000179055565b610ef9338383613806565b612b55613290565b604051602001612b6490614eb8565b6040516020818303038152906040528051906020012081604051602001612b8b9190614e1c565b6040516020818303038152906040528051906020012014612bbf57604051635ee88f9760e01b815260040160405180910390fd5b61010954610100900460ff1615612be95760405163249fab5d60e01b815260040160405180910390fd5b60005b61010054811015612c83576101008181548110612c1957634e487b7160e01b600052603260045260246000fd5b9060005260206000200154838281518110612c4457634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161015612c7157604051638a164f6360e01b815260040160405180910390fd5b80612c7b8161598b565b915050612bec565b50610100545b8251811015612cd757610100805460018101825560009182527f45e010b9ae401e2eb71529478da8bd513a9bdc2d095a111e324f5b95c09ed87b015580612ccf8161598b565b915050612c89565b508151612cec90610105906020850190613dd0565b505050565b612cf9613290565b604051602001612d0890614eb8565b6040516020818303038152906040528051906020012081604051602001612d2f9190614e1c565b6040516020818303038152906040528051906020012014612d6357604051635ee88f9760e01b815260040160405180910390fd5b50610109805463ff00000019166301000000179055565b612d82613290565b604051602001612d9190614eb8565b6040516020818303038152906040528051906020012081604051602001612db89190614e1c565b6040516020818303038152906040528051906020012014612dec57604051635ee88f9760e01b815260040160405180910390fd5b50610109805462ff0000191662010000179055565b6060610101600401805480602002602001604051908101604052809291908181526020018280548015612e7f57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612e425790505b5050505050905090565b337386b82972282dd22348374bc63fd21620f7ed847b14612ebd5760405163016bdfed60e71b815260040160405180910390fd5b61010480546001600160a01b0319166001600160a01b0392909216919091179055565b612ee8613290565b604051602001612ef790614eb8565b6040516020818303038152906040528051906020012081604051602001612f1e9190614e1c565b6040516020818303038152906040528051906020012014612f5257604051635ee88f9760e01b815260040160405180910390fd5b50610109805460ff19166001179055565b612f6b613290565b61010954600160201b900460ff1615612f975760405163249fab5d60e01b815260040160405180910390fd5b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038516331480612fd65750612fd68533610ba9565b612ff25760405162461bcd60e51b8152600401610cbe906151a0565b6110cf85858585856138e7565b613007613290565b6001600160a01b03811661306c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610cbe565b611704816137b4565b61307d613290565b610109546301000000900460ff16156130a95760405163249fab5d60e01b815260040160405180910390fd5b6113886130b96020830183614b3d565b61ffff1611156130dc576040516306b7c75960e31b815260040160405180910390fd5b60015b6130ec602083018361548e565b905081101561320c57611388613105602084018461548e565b8381811061312357634e487b7160e01b600052603260045260246000fd5b905060400201602001602081019061313b9190614b3d565b61ffff1611806131dc5750613153602083018361548e565b61315e600184615618565b81811061317b57634e487b7160e01b600052603260045260246000fd5b6131919260206040909202019081019150614b3d565b61ffff166131a2602084018461548e565b838181106131c057634e487b7160e01b600052603260045260246000fd5b6131d69260206040909202019081019150614b3d565b61ffff16115b156131fa576040516306b7c75960e31b815260040160405180910390fd5b806132048161598b565b9150506130df565b5080610107612cec8282615c0a565b60006001600160e01b03198216636cdb3d1360e11b148061324c57506001600160e01b031982166303a24d0760e21b145b80610d0957506301ffc9a760e01b6001600160e01b0319831614610d09565b60006001600160e01b0319821663152a902d60e11b1480610d095750610d098261321b565b6097546001600160a01b031633146122a95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610cbe565b60008082118015610d0957505061010054101590565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806133375761333c565b61331a565b50819003601f19909101908152919050565b81518351146133b05760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610cbe565b6001600160a01b0384166133d65760405162461bcd60e51b8152600401610cbe906151ee565b3360005b84518110156134dc57600085828151811061340557634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061343157634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526065835260408082206001600160a01b038e1683529093529190912054909150818110156134825760405162461bcd60e51b8152600401610cbe90615233565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906134c19084906155c1565b92505081905550505050806134d59061598b565b90506133da565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161352c929190614f81565b60405180910390a4610f6e818787878787613a15565b600054610100900460ff166135695760405162461bcd60e51b8152600401610cbe9061527d565b61170481613b80565b600054610100900460ff166135995760405162461bcd60e51b8152600401610cbe9061527d565b6122a9613bb0565b6127106001600160601b038216111561360f5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610cbe565b6001600160a01b0382166136655760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610cbe565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760c955565b6001600160a01b0384166136fe5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610cbe565b33600061370a85613be0565b9050600061371785613be0565b905060008681526065602090815260408083206001600160a01b038b1684529091528120805487929061374b9084906155c1565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46137ab83600089898989613c39565b50505050505050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316141561387a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610cbe565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b03841661390d5760405162461bcd60e51b8152600401610cbe906151ee565b33600061391985613be0565b9050600061392685613be0565b905060008681526065602090815260408083206001600160a01b038c1684529091529020548581101561396b5760405162461bcd60e51b8152600401610cbe90615233565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a168252812080548892906139aa9084906155c1565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613a0a848a8a8a8a8a613c39565b505050505050505050565b6001600160a01b0384163b15610f6e5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613a599089908990889088908890600401614ecb565b602060405180830381600087803b158015613a7357600080fd5b505af1925050508015613aa3575060408051601f3d908101601f19168201909252613aa09181019061475a565b60015b613b5057613aaf6159f9565b806308c379a01415613ae95750613ac4615a11565b80613acf5750613aeb565b8060405162461bcd60e51b8152600401610cbe919061506c565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610cbe565b6001600160e01b0319811663bc197c8160e01b146137ab5760405162461bcd60e51b8152600401610cbe90615158565b600054610100900460ff16613ba75760405162461bcd60e51b8152600401610cbe9061527d565b61170481613d03565b600054610100900460ff16613bd75760405162461bcd60e51b8152600401610cbe9061527d565b6122a9336137b4565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613c2857634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b15610f6e5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613c7d9089908990889088908890600401614f29565b602060405180830381600087803b158015613c9757600080fd5b505af1925050508015613cc7575060408051601f3d908101601f19168201909252613cc49181019061475a565b60015b613cd357613aaf6159f9565b6001600160e01b0319811663f23a6e6160e01b146137ab5760405162461bcd60e51b8152600401610cbe90615158565b8051610ef99060679060208401905b828054613d1e9061592a565b90600052602060002090601f016020900481019282613d405760008555613d86565b82601f10613d5957805160ff1916838001178555613d86565b82800160010185558215613d86579182015b82811115613d86578251825591602001919060010190613d6b565b50613d92929150613e76565b5090565b828054828255906000526020600020908101928215613d865791602002820182811115613d86578251825591602001919060010190613d6b565b82805482825590600052602060002090600701600890048101928215613d865791602002820160005b83821115613e3d57835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302613df9565b8015613e6d5782816101000a81549063ffffffff0219169055600401602081600301049283019260010302613e3d565b5050613d929291505b5b80821115613d925760008155600101613e77565b8035613e9681615d2e565b919050565b60008083601f840112613eac578182fd5b5081356001600160401b03811115613ec2578182fd5b6020830191508360208260051b850101111561108357600080fd5b600082601f830112613eed578081fd5b81356020613efa8261559e565b604051613f07828261595f565b8381528281019150858301600585901b87018401881015613f26578586fd5b855b85811015613f4d578135613f3b81615d2e565b84529284019290840190600101613f28565b5090979650505050505050565b600082601f830112613f6a578081fd5b81356020613f778261559e565b604051613f84828261595f565b8381528281019150858301600585901b87018401881015613fa3578586fd5b855b85811015613f4d57813584529284019290840190600101613fa5565b600082601f830112613fd1578081fd5b81356020613fde8261559e565b604051613feb828261595f565b8381528281019150858301600585901b8701840188101561400a578586fd5b855b85811015613f4d57813561401f81615d69565b8452928401929084019060010161400c565b80358015158114613e9657600080fd5b60008083601f840112614052578182fd5b5081356001600160401b03811115614068578182fd5b60208301915083602082850101111561108357600080fd5b600082601f830112614090578081fd5b81356001600160401b038111156140a9576140a96159bc565b6040516140c0601f8301601f19166020018261595f565b8181528460208386010111156140d4578283fd5b816020850160208301379081016020019190915292915050565b600060408284031215610f59578081fd5b80356001600160801b0381168114613e9657600080fd5b8035613e9681615d69565b600060208284031215614132578081fd5b813561413d81615d2e565b9392505050565b60008060408385031215614156578081fd5b823561416181615d2e565b9150602083013561417181615d2e565b809150509250929050565b600080600080600060a08688031215614193578081fd5b853561419e81615d2e565b945060208601356141ae81615d2e565b935060408601356001600160401b03808211156141c9578283fd5b6141d589838a01613f5a565b945060608801359150808211156141ea578283fd5b6141f689838a01613f5a565b9350608088013591508082111561420b578283fd5b5061421888828901614080565b9150509295509295909350565b600080600080600060a0868803121561423c578283fd5b853561424781615d2e565b9450602086013561425781615d2e565b9350604086013592506060860135915060808601356001600160401b0381111561427f578182fd5b61421888828901614080565b6000806040838503121561429d578182fd5b82356142a881615d2e565b91506142b660208401614031565b90509250929050565b600080604083850312156142d1578182fd5b82356142dc81615d2e565b946020939093013593505050565b600080604083850312156142fc578182fd5b823561430781615d2e565b9150602083013561417181615d59565b600060208284031215614328578081fd5b81356001600160401b0381111561433d578182fd5b61434984828501613edd565b949350505050565b60008060408385031215614363578182fd5b82356001600160401b0380821115614379578384fd5b61438586838701613edd565b9350602085013591508082111561439a578283fd5b506143a785828601613f5a565b9150509250929050565b600080600080600080600080600060a08a8c0312156143ce578687fd5b89356001600160401b03808211156143e4578889fd5b6143f08d838e01613e9b565b909b50995060208c0135915080821115614408578889fd5b6144148d838e01613e9b565b909950975060408c013591508082111561442c578586fd5b6144388d838e01613e9b565b909750955060608c0135915061444d82615d2e565b90935060808b01359080821115614462578384fd5b5061446f8c828d01614041565b915080935050809150509295985092959850929598565b60006020808385031215614498578182fd5b82516001600160401b038111156144ad578283fd5b8301601f810185136144bd578283fd5b80516144c88161559e565b6040516144d5828261595f565b8281528481019150838501600584901b850186018910156144f4578687fd5b8694505b838510156145165780518352600194909401939185019185016144f8565b50979650505050505050565b60008060408385031215614534578182fd5b82356001600160401b038082111561454a578384fd5b61455686838701613fc1565b9350602085013591508082111561456b578283fd5b506143a785828601614080565b600060208284031215614589578081fd5b61413d82614031565b6000602082840312156145a3578081fd5b5035919050565b6000806000606084860312156145be578081fd5b833592506020840135915060408401356001600160401b03808211156145e2578283fd5b9085019061018082880312156145f6578283fd5b6145fe615575565b614607836140ff565b8152614615602084016140ff565b6020820152614626604084016140ff565b604082015261463760608401614116565b606082015261464860808401614116565b608082015261465960a08401614116565b60a082015261466a60c08401614116565b60c082015261467b60e08401614116565b60e082015261010061468e818501614116565b908201526101206146a0848201614031565b9082015261014083810135838111156146b7578586fd5b6146c38a828701613fc1565b82840152505061016091506146d9828401613e8b565b828201528093505050509250925092565b6000806000606084860312156146fe578081fd5b833592506020840135915060408401356001600160401b03811115614721578182fd5b84016101208187031215614733578182fd5b809150509250925092565b60006020828403121561474f578081fd5b813561413d81615d43565b60006020828403121561476b578081fd5b815161413d81615d43565b600060208284031215614787578081fd5b81356001600160401b0381111561479c578182fd5b61434984828501614080565b600080600080608085870312156147bd578182fd5b84356001600160401b03808211156147d3578384fd5b6147df88838901614080565b955060208701359150808211156147f4578384fd5b61480088838901614080565b94506040870135915080821115614815578384fd5b5085016101408188031215614828578283fd5b9150606085013561483881615d2e565b939692955090935050565b60008060008060008060008060008060c08b8d031215614861578384fd5b8a356001600160401b0380821115614877578586fd5b6148838e838f016140ee565b9b5060208d0135915080821115614898578586fd5b6148a48e838f01613e9b565b909b50995060408d01359150808211156148bc578586fd5b6148c88e838f01613e9b565b909950975060608d01359150808211156148e0578586fd5b6148ec8e838f01613e9b565b909750955085915061490060808e01613e8b565b945060a08d0135915080821115614915578283fd5b506149228d828e01614041565b915080935050809150509295989b9194979a5092959850565b600080600080600060808688031215614952578283fd5b85356001600160401b0380821115614968578485fd5b61497489838a016140ee565b9650602088013595506040880135915061498d82615d2e565b909350606087013590808211156149a2578283fd5b506149af88828901614041565b969995985093965092949392505050565b600080600080600080600060c0888a0312156149da578081fd5b87356001600160401b03808211156149f0578283fd5b6149fc8b838c016140ee565b985060208a0135975060408a01359150614a1582615d2e565b90955060608901359450608089013590614a2e82615d2e565b90935060a08901359080821115614a43578283fd5b50614a508a828b01614041565b989b979a50959850939692959293505050565b60008060008060008060a08789031215614a7b578384fd5b86356001600160401b0380821115614a91578586fd5b614a9d8a838b016140ee565b9750602089013596506040890135955060608901359150614abd82615d2e565b90935060808801359080821115614ad2578384fd5b50614adf89828a01614041565b979a9699509497509295939492505050565b600060208284031215614b02578081fd5b81356001600160401b03811115614b17578182fd5b614349848285016140ee565b600060208284031215614b34578081fd5b61413d826140ff565b600060208284031215614b4e578081fd5b813561413d81615d59565b600060208284031215614b6a578081fd5b5051919050565b60008060408385031215614b83578182fd5b50508035926020909101359150565b600060208284031215614ba3578081fd5b813561413d81615d69565b6000815180845260208085019450808401835b83811015614bdd57815187529582019590820190600101614bc1565b509495945050505050565b805480835260008281526020808220940193909190825b82600782011015614c7757815463ffffffff8082168852602082811c821690890152604082811c821690890152606082811c821690890152608082811c82169089015260a082811c82169089015260c082811c9091169088015260e090811c9087015261010090950194600190910190600801614bff565b90549082811015614c955763ffffffff821686526020909501946001015b82811015614cb557602082901c63ffffffff168652602095909501946001015b82811015614cd45763ffffffff604083901c1686526020909501946001015b82811015614cf35763ffffffff606083901c1686526020909501946001015b82811015614d125763ffffffff608083901c1686526020909501946001015b82811015614d315763ffffffff60a083901c1686526020909501946001015b82811015614d505763ffffffff60c083901c1686526020909501946001015b82811015614d665760e082901c86526020860195505b5093949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614db181602086016020860161581a565b601f01601f19169290920160200192915050565b600060018060a01b0380835116845280602084015116602085015250604082015160806040850152614dfa6080850182614bae565b905060608301518482036060860152614e138282614bae565b95945050505050565b60008251614e2e81846020870161581a565b9190910192915050565b6000808454614e468161592a565b60018281168015614e5e5760018114614e6f57614e9b565b60ff19841687528287019450614e9b565b8886526020808720875b85811015614e925781548a820152908401908201614e79565b50505082870194505b505050508351614eaf81836020880161581a565b01949350505050565b663337b932bb32b960c91b815260070190565b6001600160a01b0386811682528516602082015260a060408201819052600090614ef790830186614bae565b8281036060840152614f098186614bae565b90508281036080840152614f1d8185614d99565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090614f6390830184614d99565b979650505050505050565b60208152600061413d6020830184614bae565b604081526000614f946040830185614bae565b8281036020840152614e138185614bae565b600060a0820160a0835280885480835260c08501915089845260209250828420845b82811015614fe457815484529284019260019182019101614fc8565b50505083810382850152614ff88189614be8565b915050828103604084015261500d8187614be8565b60608401959095525050608001529392505050565b6020808252825182820181905260009190848201906040850190845b8181101561506057835163ffffffff168352928401929184019160010161503e565b50909695505050505050565b60208152600061413d6020830184614d99565b60006101208083526150938184018d614d99565b9050602060018060a01b03808d16828601526040818d1681870152818c16606087015263ffffffff8b16608087015261ffff9150818a1660a087015281891660c087015281881660e087015285840361010087015280840182885116855283880151828587015281815180845260608801915086830197508893505b8084101561513f57875180518716835287810151871688840152978701976001949094019392509084019061510f565b50809750505050505050509a9950505050505050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060a082018783526020878185015286604085015260018060a01b03808716606086015260a0608086015282865180855260c0870191508388019450855b81811015615325578551841683529484019491840191600101615307565b50909b9a5050505050505050505050565b60006101008b83528a6020840152806040840152893581840152506020890135601e198a3603018112615367578182fd5b890180356001600160401b0381111561537e578283fd5b8060051b8036038c1315615390578384fd5b604061012086015261014085018290526101606001600160fb1b038311156153b6578485fd5b816020850182880137818601935080840192508483528b60608701528a60808701528960a0870152808685030160c087015250506153f5818789614d70565b91505082810360e084015261540a8185614dc5565b9c9b505050505050505050505050565b6001600160801b038c811682528b811660208301528a16604082015263ffffffff8981166060830152888116608083015287811660a083015286811660c083015285811660e083015284166101008201528215156101208201526001600160a01b038216610140820152610160810161540a565b6000808335601e198436030181126154a4578283fd5b8301803591506001600160401b038211156154bd578283fd5b6020019150600681901b360382131561108357600080fd5b6000808335601e198436030181126154eb578283fd5b8301803591506001600160401b03821115615504578283fd5b6020019150600581901b360382131561108357600080fd5b6000808335601e19843603018112615532578283fd5b8301803591506001600160401b0382111561554b578283fd5b60200191503681900382131561108357600080fd5b60008235603e19833603018112614e2e578182fd5b60405161018081016001600160401b0381118282101715615598576155986159bc565b60405290565b60006001600160401b038211156155b7576155b76159bc565b5060051b60200190565b600082198211156155d4576155d46159a6565b500190565b6000826155f457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615613576156136159a6565b500290565b60008282101561562a5761562a6159a6565b500390565b5b81811015610ef95760008155600101615630565b600160401b831115615658576156586159bc565b8054838255808410156156b1578160005260206000206007850160031c8101601c8660021b16801561569b576000198083018054828460200360031b1c16815550505b506156ae6007840160031c83018261562f565b50505b506000818152602081208391805b868110156137ab576156f36156d3856159ec565b845463ffffffff600386901b81811b801990931693909116901b16178455565b602084019350600482019150601c82111561571357600091506001830192505b6001016156bf565b6001600160401b03831115615732576157326159bc565b61573c815461592a565b600080601f8611601f84118181171561575b5760008681526020902092505b801561578a57601f880160051c830160208910156157765750825b615788601f870160051c85018261562f565b505b5080600181146157be576000945087156157a5578387013594505b600188901b60001960038a901b1c198616178655615810565b601f198816945082845b868110156157e857888601358255602095860195600190920191016157c8565b50888610156158055760001960f88a60031b161c19858901351681555b5060018860011b0186555b5050505050505050565b60005b8381101561583557818101518382015260200161581d565b83811115615844576000848401525b50505050565b813561585581615d59565b815461ffff191661ffff82161782555060018082016020840135601e1985360301811261588157600080fd5b840180356001600160401b0381111561589957600080fd5b6020820191508060061b36038213156158b157600080fd5b600160401b8111156158c5576158c56159bc565b8254818455808210156158fa576000848152602081208381019083015b808210156158f657828255908701906158e2565b5050505b50600092835260208320925b818110156137ab576159188385615cea565b92840192604092909201918401615906565b600181811c9082168061593e57607f821691505b60208210811415610f5957634e487b7160e01b600052602260045260246000fd5b601f8201601f191681016001600160401b0381118282101715615984576159846159bc565b6040525050565b600060001982141561599f5761599f6159a6565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610d0981615d2e565b60008135610d0981615d59565b60008135610d0981615d69565b600060033d1115615a0e57600481823e5160e01c5b90565b600060443d1015615a1f5790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615a4e57505050505090565b8285019150815181811115615a665750505050505090565b843d8701016020828501011115615a805750505050505090565b615a8f6020828601018761595f565b509095945050505050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b615ac4828361551c565b615acf81838561571b565b5050615ae9615ae0602084016159d2565b60018301615a9a565b615b01615af8604084016159d2565b60028301615a9a565b615b19615b10606084016159d2565b60038301615a9a565b615b2660808301836154d5565b615b34818360048601615644565b505060058101615b60615b4960a085016159ec565b825463ffffffff191663ffffffff91909116178255565b615b8d615b6f60c085016159df565b825465ffff00000000191660209190911b65ffff0000000016178255565b615bbe615b9c60e085016159df565b825467ffff000000000000191660309190911b67ffff00000000000016178255565b615bef615bce61010085016159df565b825461ffff60401b191660409190911b69ffff000000000000000016178255565b50610ef9615c01610120840184615560565b6006830161584a565b8135615c1581615d59565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615c4157600080fd5b840180356001600160401b03811115615c5957600080fd5b6020820191508060061b3603821315615c7157600080fd5b600160401b811115615c8557615c856159bc565b825481845580821015615cba576000848152602081208381019083015b80821015615cb65782825590870190615ca2565b5050505b50600092835260208320925b818110156137ab57615cd88385615cea565b92840192604092909201918401615cc6565b8135615cf581615d59565b815461ffff191661ffff8216178255506020820135615d1381615d59565b815463ffff0000191660109190911b63ffff00001617905550565b6001600160a01b038116811461170457600080fd5b6001600160e01b03198116811461170457600080fd5b61ffff8116811461170457600080fd5b63ffffffff8116811461170457600080fdfea2646970667358221220caa72b60b00cd020d8050a12f1553066e3c14ed773dd3cba2949ae6d44eb243164736f6c63430008040033
Deployed Bytecode
0x6080604052600436106103195760003560e01c806355f804b3116101ab578063a3edb86a116100f7578063d71d8d2311610095578063ead005531161006f578063ead0055314610bd7578063f242432a14610bf7578063f2fde38b14610c17578063fd614f2a14610c3757600080fd5b8063d71d8d2314610b4e578063de6cd0db14610b6e578063e985e9c514610b8e57600080fd5b8063bedcf003116100d1578063bedcf00314610a7a578063c7494df714610aec578063ce216e2f14610b0c578063d5abeb0114610b2c57600080fd5b8063a3edb86a14610958578063a5aa4aa41461099b578063b2938bd414610a5a57600080fd5b80637ded184811610164578063978a45091161013e578063978a4509146108a15780639a7a973c146108eb578063a15947c414610918578063a22cb4651461093857600080fd5b80637ded18481461085b5780638da5cb5b1461086e57806395d89b411461088c57600080fd5b806355f804b31461079c5780635ecb16cd146107bc5780636f33659f146107dc578063715018a6146107fc57806379502c55146108115780637c5d0a081461083b57600080fd5b80632a55205a1161026a5780634331f639116102235780634a21a2df116101fd5780634a21a2df1461070e5780634bde38c8146107215780634e1273f41461075c5780635000d3d11461078957600080fd5b80634331f639146106ae57806343a11bc9146106ce57806347286bc0146106ee57600080fd5b80632a55205a146105e75780632eb2c2d61461062657806331e1fdac1461064657806332f7c6d4146106665780633a24417a146106865780633ccfd60b1461069957600080fd5b80631069143a116102d75780631fff79b0116102b15780631fff79b0146104b557806321d5bf24146104c85780632693ebf21461052f57806327a594371461054f57600080fd5b80631069143a146103fa578063109695231461048057806318160ddd146104a057600080fd5b8062fdd58e1461031e57806301ffc9a71461035157806306fdde03146103815780630c6f910b146103a35780630e89341c146103c55780630f7309e8146103e5575b600080fd5b34801561032a57600080fd5b5061033e6103393660046142bf565b610c57565b6040519081526020015b60405180910390f35b34801561035d57600080fd5b5061037161036c36600461473e565b610cef565b6040519015158152602001610348565b34801561038d57600080fd5b50610396610d0f565b604051610348919061506c565b3480156103af57600080fd5b506103c36103be366004614b3d565b610d9e565b005b3480156103d157600080fd5b506103966103e0366004614592565b610e1c565b3480156103f157600080fd5b50610396610ea1565b34801561040657600080fd5b50610109546104479060ff80821691610100810482169162010000820481169163010000008104821691600160201b82048116916501000000000090041686565b604080519615158752941515602087015292151593850193909352151560608401529015156080830152151560a082015260c001610348565b34801561048c57600080fd5b506103c361049b366004614776565b610eaf565b3480156104ac57600080fd5b5061033e610efd565b6103c36104c3366004614a63565b610f5f565b3480156104d457600080fd5b506105176104e3366004614144565b6001600160a01b03918216600090815260ff602090815260408083209390941682529190915220546001600160801b031690565b6040516001600160801b039091168152602001610348565b34801561053b57600080fd5b5061033e61054a366004614592565b610f76565b34801561055b57600080fd5b506105c061056a366004614121565b6040805180820190915260008082526020820152506001600160a01b0316600090815260fe60209081526040918290208251808401909352546001600160801b038082168452600160801b909104169082015290565b6040805182516001600160801b039081168252602093840151169281019290925201610348565b3480156105f357600080fd5b50610607610602366004614b71565b610fdc565b604080516001600160a01b039093168352602083019190915201610348565b34801561063257600080fd5b506103c361064136600461417c565b61108a565b34801561065257600080fd5b506103c36106613660046147a8565b6110d6565b34801561067257600080fd5b506103c3610681366004614776565b611557565b6103c36106943660046143b1565b6115e1565b3480156106a557600080fd5b506103c3611696565b3480156106ba57600080fd5b506103c36106c93660046142ea565b611707565b3480156106da57600080fd5b506103c36106e93660046146ea565b61173b565b3480156106fa57600080fd5b506103c36107093660046145aa565b611a24565b6103c361071c36600461493b565b611b75565b34801561072d57600080fd5b507386b82972282dd22348374bc63fd21620f7ed847b5b6040516001600160a01b039091168152602001610348565b34801561076857600080fd5b5061077c610777366004614351565b611b85565b6040516103489190614f6e565b6103c3610797366004614843565b611ce6565b3480156107a857600080fd5b506103c36107b7366004614776565b6121b1565b3480156107c857600080fd5b506103c36107d7366004614317565b6121f2565b3480156107e857600080fd5b506103c36107f7366004614b92565b612272565b34801561080857600080fd5b506103c3612297565b34801561081d57600080fd5b506108266122ab565b6040516103489998979695949392919061507f565b34801561084757600080fd5b506103c3610856366004614776565b61241b565b6103c36108693660046149c0565b6124a0565b34801561087a57600080fd5b506097546001600160a01b0316610744565b34801561089857600080fd5b50610396612aa7565b3480156108ad57600080fd5b506105176108bc366004614121565b6001600160a01b0316600090815260ff602090815260408083208380529091529020546001600160801b031690565b3480156108f757600080fd5b5061033e610906366004614592565b600090815260fd602052604090205490565b34801561092457600080fd5b506103c3610933366004614776565b612ab5565b34801561094457600080fd5b506103c361095336600461428b565b612b42565b34801561096457600080fd5b5061033e6109733660046142bf565b6001600160a01b0391909116600090815260fc60209081526040808320938352929052205490565b3480156109a757600080fd5b50610a436109b6366004614592565b60fb6020526000908152604090208054600182015460028301546004909301546001600160801b0380841694600160801b948590048216949184169391820463ffffffff90811693600160a01b8404821693600160c01b8104831693600160e01b90910483169280821692600160201b830490911691600160401b900460ff16906001600160a01b03168b565b6040516103489b9a9998979695949392919061541a565b348015610a6657600080fd5b506103c3610a75366004614522565b612b4d565b348015610a8657600080fd5b5060408051808201825260008082526020918201819052805260fe815281518083019092527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af546001600160801b038082168452600160801b90910416908201526105c0565b348015610af857600080fd5b506103c3610b07366004614776565b612cf1565b348015610b1857600080fd5b506103c3610b27366004614776565b612d7a565b348015610b3857600080fd5b50610b41612e01565b6040516103489190615022565b348015610b5a57600080fd5b506103c3610b69366004614121565b612e89565b348015610b7a57600080fd5b506103c3610b89366004614776565b612ee0565b348015610b9a57600080fd5b50610371610ba9366004614144565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b348015610be357600080fd5b506103c3610bf2366004614121565b612f63565b348015610c0357600080fd5b506103c3610c12366004614225565b612fba565b348015610c2357600080fd5b506103c3610c32366004614121565b612fff565b348015610c4357600080fd5b506103c3610c52366004614af1565b613075565b60006001600160a01b038316610cc75760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060009081526065602090815260408083206001600160a01b03949094168352929052205490565b6000610cfa8261321b565b80610d095750610d098261326b565b92915050565b61010a8054610d1d9061592a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d499061592a565b8015610d965780601f10610d6b57610100808354040283529160200191610d96565b820191906000526020600020905b815481529060010190602001808311610d7957829003601f168201915b505050505081565b610da6613290565b6101095462010000900460ff1615610dd15760405163249fab5d60e01b815260040160405180910390fd5b61138861ffff82161115610df8576040516306b7c75960e31b815260040160405180910390fd5b610106805461ffff909216600160201b0265ffff0000000019909216919091179055565b6060610e27826132ea565b610e4457604051630a14c4b560e41b815260040160405180910390fd5b6101018054610e529061592a565b15159050610e6f5760405180602001604052806000815250610d09565b610101610e7b83613300565b604051602001610e8c929190614e38565b60405160208183030381529060405292915050565b61010c8054610d1d9061592a565b610eb7613290565b6101095465010000000000900460ff1615610ee55760405163249fab5d60e01b815260040160405180910390fd5b8051610ef99061010c906020840190613d12565b5050565b600080805b61010054811015610f59576101008181548110610f2f57634e487b7160e01b600052603260045260246000fd5b906000526020600020015482610f4591906155c1565b915080610f518161598b565b915050610f02565b50919050565b610f6e868633878787876124a0565b505050505050565b6000610f81826132ea565b610f9e57604051630a14c4b560e41b815260040160405180910390fd5b610100610fac600184615618565b81548110610fca57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b600082815260ca602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161105157506040805180820190915260c9546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090611070906001600160601b0316876155f9565b61107a91906155d9565b91519350909150505b9250929050565b6001600160a01b0385163314806110a657506110a68533610ba9565b6110c25760405162461bcd60e51b8152600401610cbe906151a0565b6110cf858585858561334e565b5050505050565b600054610100900460ff16158080156110f65750600054600160ff909116105b806111105750303b158015611110575060005460ff166001145b6111735760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610cbe565b6000805460ff191660011790558015611196576000805461ff0019166101001790555b84516111aa9061010a906020880190613d12565b5083516111bf9061010b906020870190613d12565b506111d860405180602001604052806000815250613542565b6113886111eb60e0850160c08601614b3d565b61ffff161180611210575061138861120a610100850160e08601614b3d565b61ffff16115b8061123057506101f461122a610100850160e08601614b3d565b61ffff16105b8061125b5750611388611247610120850185615560565b611255906020810190614b3d565b61ffff16115b8061127e575060006112736040850160208601614121565b6001600160a01b0316145b8061129c575061129460c0840160a08501614b92565b63ffffffff16155b156112ba576040516306b7c75960e31b815260040160405180910390fd5b60015b6112cb610120850185615560565b6112d990602081019061548e565b9050811015611426576113886112f3610120860186615560565b61130190602081019061548e565b8381811061131f57634e487b7160e01b600052603260045260246000fd5b90506040020160200160208101906113379190614b3d565b61ffff1611806113f65750611350610120850185615560565b61135e90602081019061548e565b611369600184615618565b81811061138657634e487b7160e01b600052603260045260246000fd5b61139c9260206040909202019081019150614b3d565b61ffff166113ae610120860186615560565b6113bc90602081019061548e565b838181106113da57634e487b7160e01b600052603260045260246000fd5b6113f09260206040909202019081019150614b3d565b61ffff16115b15611414576040516306b7c75960e31b815260040160405180910390fd5b8061141e8161598b565b9150506112bd565b50826101016114358282615aba565b50611445905060808401846154d5565b90506001600160401b0381111561146c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611495578160200160208202803683370190505b5080516114ab9161010091602090910190613d96565b506114b4613572565b610103546001600160a01b0316156114f15761010354610106546114ec916001600160a01b031690600160401b900461ffff16611707565b61150b565b6101065461150b908390600160401b900461ffff16611707565b80156110cf576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b61155f613290565b60405160200161156e90614eb8565b60405160208183030381529060405280519060200120816040516020016115959190614e1c565b60405160208183030381529060405280519060200120146115c957604051635ee88f9760e01b815260040160405180910390fd5b50610109805464ff000000001916600160201b179055565b60005b8881101561168a576116788a8a8381811061160f57634e487b7160e01b600052603260045260246000fd5b90506020028101906116219190615560565b89898481811061164157634e487b7160e01b600052603260045260246000fd5b905060200201353389898681811061166957634e487b7160e01b600052603260045260246000fd5b905060200201358888886124a0565b806116828161598b565b9150506115e4565b50505050505050505050565b604080516001808252818301909252600091602080830190803683370190505090506000816000815181106116db57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050611704816121f2565b50565b61170f613290565b610106805461ffff60401b1916600160401b61ffff841690810291909117909155610ef99083906135a1565b611743613290565b6040805161018081019091528061175d6020840184614b23565b6001600160801b0316815260209081019061177a90840184614b23565b6001600160801b0316815260200160006001600160801b031681526020018260200160208101906117ab9190614b92565b63ffffffff1681526020016117c66060840160408501614b92565b63ffffffff1681526020016117e16080840160608501614b92565b63ffffffff1681526020016117fc60a0840160808501614b92565b63ffffffff1681526000602082015260400161181e60c0840160a08501614b92565b63ffffffff16815260200161183960e0840160c08501614578565b1515815260200161184d60e08401846154d5565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161189661012084016101008501614121565b6001600160a01b03169052600084815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b911515919091021790925561014083015180516119c79260038501920190613dd0565b506101609190910151600490910180546001600160a01b0319166001600160a01b03909216919091179055604051829084907fe9a0c17645ed78ccc9996259f00297ffc75e6b9d22cd605ccc9992cc8ca3f4c190600090a3505050565b611a2c613290565b42816060015163ffffffff161015611a4b5763ffffffff421660608201525b600083815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b911515919091021790925561014083015180518493926119c7926003850192910190613dd0565b6110cf85853360008787876124a0565b60608151835114611bea5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610cbe565b600083516001600160401b03811115611c1357634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611c3c578160200160208202803683370190505b50905060005b8451811015611cde57611ca3858281518110611c6e57634e487b7160e01b600052603260045260246000fd5b6020026020010151858381518110611c9657634e487b7160e01b600052603260045260246000fd5b6020026020010151610c57565b828281518110611cc357634e487b7160e01b600052603260045260246000fd5b6020908102919091010152611cd78161598b565b9050611c42565b509392505050565b8588141580611cf55750858414155b15611d13576040516306b7c75960e31b815260040160405180910390fd5b8935600090815260fb602052604090206002810154600160401b900460ff1680611d4f575060028101546001600160201b90910463ffffffff16115b15611d6d57604051630280e1e560e61b815260040160405180910390fd5b60408051608081018252600080825260208201526060918101829052818101919091526040518060800160405280611dad6097546001600160a01b031690565b6001600160a01b03168152602001866001600160a01b031681526020018a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208a810282810182019093528a82529283019290918b918b918291850190849080828437600081840152601f19601f82011690508083019250505050505050815250905073accc072242b2b8bc0b7ba9abeb6b5192fe533304630e3deb14836101018f60fc60fd6101008b8b8a6040518a63ffffffff1660e01b8152600401611e9699989796959493929190615336565b60006040518083038186803b158015611eae57600080fd5b505af4158015611ec2573d6000803e3d6000fd5b5050505060005b8a81101561200d576060611f5f8d8d84818110611ef657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611f0b9190614121565b8a8a85818110611f2b57634e487b7160e01b600052603260045260246000fd5b905060200201358d8d86818110611f5257634e487b7160e01b600052603260045260246000fd5b905060200201358461369e565b8a8a83818110611f7f57634e487b7160e01b600052603260045260246000fd5b9050602002013561010060018b8b86818110611fab57634e487b7160e01b600052603260045260246000fd5b90506020020135611fbc9190615618565b81548110611fda57634e487b7160e01b600052603260045260246000fd5b906000526020600020016000828254611ff391906155c1565b9091555082915061200590508161598b565b915050611ec9565b506000805b89811015612060578a8a8281811061203a57634e487b7160e01b600052603260045260246000fd5b905060200201358261204c91906155c1565b9150806120588161598b565b915050612012565b50600183015463ffffffff600160e01b82048116600160c01b9092041610156120d3578060fc6000336001600160a01b03166001600160a01b0316815260200190815260200160002060008f60000135815260200190815260200160002060008282546120cd91906155c1565b90915550505b600183015463ffffffff600160e01b90910481161015612113578c35600090815260fd60205260408120805483929061210d9084906155c1565b90915550505b6040516329ba982960e21b815260048101849052610101602482015260fe604482015260ff60648201526001600160a01b038716608482015260a4810182905273accc072242b2b8bc0b7ba9abeb6b5192fe5333049063a6ea60a49060c40160006040518083038186803b15801561218a57600080fd5b505af415801561219e573d6000803e3d6000fd5b5050505050505050505050505050505050565b6121b9613290565b6101095460ff16156121de5760405163249fab5d60e01b815260040160405180910390fd5b8051610ef990610101906020840190613d12565b73accc072242b2b8bc0b7ba9abeb6b5192fe5333046360f0e59661010160fe60ff6122256097546001600160a01b031690565b866040518663ffffffff1660e01b81526004016122469594939291906152c8565b60006040518083038186803b15801561225e57600080fd5b505af41580156110cf573d6000803e3d6000fd5b61227a613290565b610106805463ffffffff191663ffffffff92909216919091179055565b61229f613290565b6122a960006137b4565b565b610101805481906122bb9061592a565b80601f01602080910402602001604051908101604052809291908181526020018280546122e79061592a565b80156123345780601f1061230957610100808354040283529160200191612334565b820191906000526020600020905b81548152906001019060200180831161231757829003601f168201915b505050600184015460028501546003860154600587015460408051808201825260068a01805461ffff908116835260078c01805485516020828102820181019097528181529c9d6001600160a01b039a8b169d998b169c5097909916995063ffffffff861698600160201b870483169866010000000000008804841698600160401b90980490931696958086019392919060009084015b8282101561240e576000848152602090819020604080518082019091529084015461ffff80821683526201000090910416818301528252600190920191016123cb565b5050505081525050905089565b612423613290565b60405160200161243290614eb8565b60405160208183030381529060405280519060200120816040516020016124599190614e1c565b604051602081830303815290604052805190602001201461248d57604051635ee88f9760e01b815260040160405180910390fd5b50610109805461ff001916610100179055565b8635600090815260fb6020526040902060028101546001600160201b90910463ffffffff1611156124ea5760028101546124e790600160201b900463ffffffff16886155f9565b96505b604080516080810182526000808252602082015260609181018290528181019190915260028201546060908190600160401b900460ff16156126ea57600073accc072242b2b8bc0b7ba9abeb6b5192fe533304635ec01e4d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561256c57600080fd5b505af4158015612580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a49190614b59565b905073accc072242b2b8bc0b7ba9abeb6b5192fe5333046310f11a15610100610101600401886003018f866040518663ffffffff1660e01b81526004016125ef959493929190614fa6565b60006040518083038186803b15801561260757600080fd5b505af415801561261b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126439190810190614486565b925082516001600160401b0381111561266c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612695578160200160208202803683370190505b50915060005b83518110156126e35760018382815181106126c657634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806126db8161598b565b91505061269b565b5050612788565b6040805160018082528183019092529060208083019080368337019050509150878260008151811061272c57634e487b7160e01b600052603260045260246000fd5b602090810291909101015260408051600180825281830190925290816020016020820280368337019050509050898160008151811061277b57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60405180608001604052806127a56097546001600160a01b031690565b6001600160a01b03168152602001886001600160a01b03168152602001828152602001838152509250505073accc072242b2b8bc0b7ba9abeb6b5192fe533304630e3deb14836101018c60fc60fd6101008b8b8a6040518a63ffffffff1660e01b815260040161281d99989796959493929190615336565b60006040518083038186803b15801561283557600080fd5b505af4158015612849573d6000803e3d6000fd5b5050505060005b8160600151518110156129795760606128c1898460600151848151811061288757634e487b7160e01b600052603260045260246000fd5b6020026020010151856040015185815181106128b357634e487b7160e01b600052603260045260246000fd5b60200260200101518461369e565b826040015182815181106128e557634e487b7160e01b600052603260045260246000fd5b602002602001015161010060018560600151858151811061291657634e487b7160e01b600052603260045260246000fd5b60200260200101516129289190615618565b8154811061294657634e487b7160e01b600052603260045260246000fd5b90600052602060002001600082825461295f91906155c1565b9091555082915061297190508161598b565b915050612850565b50600182015463ffffffff600160e01b82048116600160c01b9092041610156129cd5733600090815260fc602090815260408083208c358452909152812080548a92906129c79084906155c1565b90915550505b600182015463ffffffff600160e01b90910481161015612a0d578835600090815260fd6020526040812080548a9290612a079084906155c1565b90915550505b6040516329ba982960e21b815260048101839052610101602482015260fe604482015260ff60648201526001600160a01b038616608482015260a4810189905273accc072242b2b8bc0b7ba9abeb6b5192fe5333049063a6ea60a49060c40160006040518083038186803b158015612a8457600080fd5b505af4158015612a98573d6000803e3d6000fd5b50505050505050505050505050565b61010b8054610d1d9061592a565b612abd613290565b604051602001612acc90614eb8565b6040516020818303038152906040528051906020012081604051602001612af39190614e1c565b6040516020818303038152906040528051906020012014612b2757604051635ee88f9760e01b815260040160405180910390fd5b50610109805465ff0000000000191665010000000000179055565b610ef9338383613806565b612b55613290565b604051602001612b6490614eb8565b6040516020818303038152906040528051906020012081604051602001612b8b9190614e1c565b6040516020818303038152906040528051906020012014612bbf57604051635ee88f9760e01b815260040160405180910390fd5b61010954610100900460ff1615612be95760405163249fab5d60e01b815260040160405180910390fd5b60005b61010054811015612c83576101008181548110612c1957634e487b7160e01b600052603260045260246000fd5b9060005260206000200154838281518110612c4457634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161015612c7157604051638a164f6360e01b815260040160405180910390fd5b80612c7b8161598b565b915050612bec565b50610100545b8251811015612cd757610100805460018101825560009182527f45e010b9ae401e2eb71529478da8bd513a9bdc2d095a111e324f5b95c09ed87b015580612ccf8161598b565b915050612c89565b508151612cec90610105906020850190613dd0565b505050565b612cf9613290565b604051602001612d0890614eb8565b6040516020818303038152906040528051906020012081604051602001612d2f9190614e1c565b6040516020818303038152906040528051906020012014612d6357604051635ee88f9760e01b815260040160405180910390fd5b50610109805463ff00000019166301000000179055565b612d82613290565b604051602001612d9190614eb8565b6040516020818303038152906040528051906020012081604051602001612db89190614e1c565b6040516020818303038152906040528051906020012014612dec57604051635ee88f9760e01b815260040160405180910390fd5b50610109805462ff0000191662010000179055565b6060610101600401805480602002602001604051908101604052809291908181526020018280548015612e7f57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612e425790505b5050505050905090565b337386b82972282dd22348374bc63fd21620f7ed847b14612ebd5760405163016bdfed60e71b815260040160405180910390fd5b61010480546001600160a01b0319166001600160a01b0392909216919091179055565b612ee8613290565b604051602001612ef790614eb8565b6040516020818303038152906040528051906020012081604051602001612f1e9190614e1c565b6040516020818303038152906040528051906020012014612f5257604051635ee88f9760e01b815260040160405180910390fd5b50610109805460ff19166001179055565b612f6b613290565b61010954600160201b900460ff1615612f975760405163249fab5d60e01b815260040160405180910390fd5b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038516331480612fd65750612fd68533610ba9565b612ff25760405162461bcd60e51b8152600401610cbe906151a0565b6110cf85858585856138e7565b613007613290565b6001600160a01b03811661306c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610cbe565b611704816137b4565b61307d613290565b610109546301000000900460ff16156130a95760405163249fab5d60e01b815260040160405180910390fd5b6113886130b96020830183614b3d565b61ffff1611156130dc576040516306b7c75960e31b815260040160405180910390fd5b60015b6130ec602083018361548e565b905081101561320c57611388613105602084018461548e565b8381811061312357634e487b7160e01b600052603260045260246000fd5b905060400201602001602081019061313b9190614b3d565b61ffff1611806131dc5750613153602083018361548e565b61315e600184615618565b81811061317b57634e487b7160e01b600052603260045260246000fd5b6131919260206040909202019081019150614b3d565b61ffff166131a2602084018461548e565b838181106131c057634e487b7160e01b600052603260045260246000fd5b6131d69260206040909202019081019150614b3d565b61ffff16115b156131fa576040516306b7c75960e31b815260040160405180910390fd5b806132048161598b565b9150506130df565b5080610107612cec8282615c0a565b60006001600160e01b03198216636cdb3d1360e11b148061324c57506001600160e01b031982166303a24d0760e21b145b80610d0957506301ffc9a760e01b6001600160e01b0319831614610d09565b60006001600160e01b0319821663152a902d60e11b1480610d095750610d098261321b565b6097546001600160a01b031633146122a95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610cbe565b60008082118015610d0957505061010054101590565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806133375761333c565b61331a565b50819003601f19909101908152919050565b81518351146133b05760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610cbe565b6001600160a01b0384166133d65760405162461bcd60e51b8152600401610cbe906151ee565b3360005b84518110156134dc57600085828151811061340557634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061343157634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526065835260408082206001600160a01b038e1683529093529190912054909150818110156134825760405162461bcd60e51b8152600401610cbe90615233565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906134c19084906155c1565b92505081905550505050806134d59061598b565b90506133da565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161352c929190614f81565b60405180910390a4610f6e818787878787613a15565b600054610100900460ff166135695760405162461bcd60e51b8152600401610cbe9061527d565b61170481613b80565b600054610100900460ff166135995760405162461bcd60e51b8152600401610cbe9061527d565b6122a9613bb0565b6127106001600160601b038216111561360f5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610cbe565b6001600160a01b0382166136655760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610cbe565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760c955565b6001600160a01b0384166136fe5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610cbe565b33600061370a85613be0565b9050600061371785613be0565b905060008681526065602090815260408083206001600160a01b038b1684529091528120805487929061374b9084906155c1565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46137ab83600089898989613c39565b50505050505050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316141561387a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610cbe565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b03841661390d5760405162461bcd60e51b8152600401610cbe906151ee565b33600061391985613be0565b9050600061392685613be0565b905060008681526065602090815260408083206001600160a01b038c1684529091529020548581101561396b5760405162461bcd60e51b8152600401610cbe90615233565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a168252812080548892906139aa9084906155c1565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613a0a848a8a8a8a8a613c39565b505050505050505050565b6001600160a01b0384163b15610f6e5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613a599089908990889088908890600401614ecb565b602060405180830381600087803b158015613a7357600080fd5b505af1925050508015613aa3575060408051601f3d908101601f19168201909252613aa09181019061475a565b60015b613b5057613aaf6159f9565b806308c379a01415613ae95750613ac4615a11565b80613acf5750613aeb565b8060405162461bcd60e51b8152600401610cbe919061506c565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610cbe565b6001600160e01b0319811663bc197c8160e01b146137ab5760405162461bcd60e51b8152600401610cbe90615158565b600054610100900460ff16613ba75760405162461bcd60e51b8152600401610cbe9061527d565b61170481613d03565b600054610100900460ff16613bd75760405162461bcd60e51b8152600401610cbe9061527d565b6122a9336137b4565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613c2857634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b15610f6e5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613c7d9089908990889088908890600401614f29565b602060405180830381600087803b158015613c9757600080fd5b505af1925050508015613cc7575060408051601f3d908101601f19168201909252613cc49181019061475a565b60015b613cd357613aaf6159f9565b6001600160e01b0319811663f23a6e6160e01b146137ab5760405162461bcd60e51b8152600401610cbe90615158565b8051610ef99060679060208401905b828054613d1e9061592a565b90600052602060002090601f016020900481019282613d405760008555613d86565b82601f10613d5957805160ff1916838001178555613d86565b82800160010185558215613d86579182015b82811115613d86578251825591602001919060010190613d6b565b50613d92929150613e76565b5090565b828054828255906000526020600020908101928215613d865791602002820182811115613d86578251825591602001919060010190613d6b565b82805482825590600052602060002090600701600890048101928215613d865791602002820160005b83821115613e3d57835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302613df9565b8015613e6d5782816101000a81549063ffffffff0219169055600401602081600301049283019260010302613e3d565b5050613d929291505b5b80821115613d925760008155600101613e77565b8035613e9681615d2e565b919050565b60008083601f840112613eac578182fd5b5081356001600160401b03811115613ec2578182fd5b6020830191508360208260051b850101111561108357600080fd5b600082601f830112613eed578081fd5b81356020613efa8261559e565b604051613f07828261595f565b8381528281019150858301600585901b87018401881015613f26578586fd5b855b85811015613f4d578135613f3b81615d2e565b84529284019290840190600101613f28565b5090979650505050505050565b600082601f830112613f6a578081fd5b81356020613f778261559e565b604051613f84828261595f565b8381528281019150858301600585901b87018401881015613fa3578586fd5b855b85811015613f4d57813584529284019290840190600101613fa5565b600082601f830112613fd1578081fd5b81356020613fde8261559e565b604051613feb828261595f565b8381528281019150858301600585901b8701840188101561400a578586fd5b855b85811015613f4d57813561401f81615d69565b8452928401929084019060010161400c565b80358015158114613e9657600080fd5b60008083601f840112614052578182fd5b5081356001600160401b03811115614068578182fd5b60208301915083602082850101111561108357600080fd5b600082601f830112614090578081fd5b81356001600160401b038111156140a9576140a96159bc565b6040516140c0601f8301601f19166020018261595f565b8181528460208386010111156140d4578283fd5b816020850160208301379081016020019190915292915050565b600060408284031215610f59578081fd5b80356001600160801b0381168114613e9657600080fd5b8035613e9681615d69565b600060208284031215614132578081fd5b813561413d81615d2e565b9392505050565b60008060408385031215614156578081fd5b823561416181615d2e565b9150602083013561417181615d2e565b809150509250929050565b600080600080600060a08688031215614193578081fd5b853561419e81615d2e565b945060208601356141ae81615d2e565b935060408601356001600160401b03808211156141c9578283fd5b6141d589838a01613f5a565b945060608801359150808211156141ea578283fd5b6141f689838a01613f5a565b9350608088013591508082111561420b578283fd5b5061421888828901614080565b9150509295509295909350565b600080600080600060a0868803121561423c578283fd5b853561424781615d2e565b9450602086013561425781615d2e565b9350604086013592506060860135915060808601356001600160401b0381111561427f578182fd5b61421888828901614080565b6000806040838503121561429d578182fd5b82356142a881615d2e565b91506142b660208401614031565b90509250929050565b600080604083850312156142d1578182fd5b82356142dc81615d2e565b946020939093013593505050565b600080604083850312156142fc578182fd5b823561430781615d2e565b9150602083013561417181615d59565b600060208284031215614328578081fd5b81356001600160401b0381111561433d578182fd5b61434984828501613edd565b949350505050565b60008060408385031215614363578182fd5b82356001600160401b0380821115614379578384fd5b61438586838701613edd565b9350602085013591508082111561439a578283fd5b506143a785828601613f5a565b9150509250929050565b600080600080600080600080600060a08a8c0312156143ce578687fd5b89356001600160401b03808211156143e4578889fd5b6143f08d838e01613e9b565b909b50995060208c0135915080821115614408578889fd5b6144148d838e01613e9b565b909950975060408c013591508082111561442c578586fd5b6144388d838e01613e9b565b909750955060608c0135915061444d82615d2e565b90935060808b01359080821115614462578384fd5b5061446f8c828d01614041565b915080935050809150509295985092959850929598565b60006020808385031215614498578182fd5b82516001600160401b038111156144ad578283fd5b8301601f810185136144bd578283fd5b80516144c88161559e565b6040516144d5828261595f565b8281528481019150838501600584901b850186018910156144f4578687fd5b8694505b838510156145165780518352600194909401939185019185016144f8565b50979650505050505050565b60008060408385031215614534578182fd5b82356001600160401b038082111561454a578384fd5b61455686838701613fc1565b9350602085013591508082111561456b578283fd5b506143a785828601614080565b600060208284031215614589578081fd5b61413d82614031565b6000602082840312156145a3578081fd5b5035919050565b6000806000606084860312156145be578081fd5b833592506020840135915060408401356001600160401b03808211156145e2578283fd5b9085019061018082880312156145f6578283fd5b6145fe615575565b614607836140ff565b8152614615602084016140ff565b6020820152614626604084016140ff565b604082015261463760608401614116565b606082015261464860808401614116565b608082015261465960a08401614116565b60a082015261466a60c08401614116565b60c082015261467b60e08401614116565b60e082015261010061468e818501614116565b908201526101206146a0848201614031565b9082015261014083810135838111156146b7578586fd5b6146c38a828701613fc1565b82840152505061016091506146d9828401613e8b565b828201528093505050509250925092565b6000806000606084860312156146fe578081fd5b833592506020840135915060408401356001600160401b03811115614721578182fd5b84016101208187031215614733578182fd5b809150509250925092565b60006020828403121561474f578081fd5b813561413d81615d43565b60006020828403121561476b578081fd5b815161413d81615d43565b600060208284031215614787578081fd5b81356001600160401b0381111561479c578182fd5b61434984828501614080565b600080600080608085870312156147bd578182fd5b84356001600160401b03808211156147d3578384fd5b6147df88838901614080565b955060208701359150808211156147f4578384fd5b61480088838901614080565b94506040870135915080821115614815578384fd5b5085016101408188031215614828578283fd5b9150606085013561483881615d2e565b939692955090935050565b60008060008060008060008060008060c08b8d031215614861578384fd5b8a356001600160401b0380821115614877578586fd5b6148838e838f016140ee565b9b5060208d0135915080821115614898578586fd5b6148a48e838f01613e9b565b909b50995060408d01359150808211156148bc578586fd5b6148c88e838f01613e9b565b909950975060608d01359150808211156148e0578586fd5b6148ec8e838f01613e9b565b909750955085915061490060808e01613e8b565b945060a08d0135915080821115614915578283fd5b506149228d828e01614041565b915080935050809150509295989b9194979a5092959850565b600080600080600060808688031215614952578283fd5b85356001600160401b0380821115614968578485fd5b61497489838a016140ee565b9650602088013595506040880135915061498d82615d2e565b909350606087013590808211156149a2578283fd5b506149af88828901614041565b969995985093965092949392505050565b600080600080600080600060c0888a0312156149da578081fd5b87356001600160401b03808211156149f0578283fd5b6149fc8b838c016140ee565b985060208a0135975060408a01359150614a1582615d2e565b90955060608901359450608089013590614a2e82615d2e565b90935060a08901359080821115614a43578283fd5b50614a508a828b01614041565b989b979a50959850939692959293505050565b60008060008060008060a08789031215614a7b578384fd5b86356001600160401b0380821115614a91578586fd5b614a9d8a838b016140ee565b9750602089013596506040890135955060608901359150614abd82615d2e565b90935060808801359080821115614ad2578384fd5b50614adf89828a01614041565b979a9699509497509295939492505050565b600060208284031215614b02578081fd5b81356001600160401b03811115614b17578182fd5b614349848285016140ee565b600060208284031215614b34578081fd5b61413d826140ff565b600060208284031215614b4e578081fd5b813561413d81615d59565b600060208284031215614b6a578081fd5b5051919050565b60008060408385031215614b83578182fd5b50508035926020909101359150565b600060208284031215614ba3578081fd5b813561413d81615d69565b6000815180845260208085019450808401835b83811015614bdd57815187529582019590820190600101614bc1565b509495945050505050565b805480835260008281526020808220940193909190825b82600782011015614c7757815463ffffffff8082168852602082811c821690890152604082811c821690890152606082811c821690890152608082811c82169089015260a082811c82169089015260c082811c9091169088015260e090811c9087015261010090950194600190910190600801614bff565b90549082811015614c955763ffffffff821686526020909501946001015b82811015614cb557602082901c63ffffffff168652602095909501946001015b82811015614cd45763ffffffff604083901c1686526020909501946001015b82811015614cf35763ffffffff606083901c1686526020909501946001015b82811015614d125763ffffffff608083901c1686526020909501946001015b82811015614d315763ffffffff60a083901c1686526020909501946001015b82811015614d505763ffffffff60c083901c1686526020909501946001015b82811015614d665760e082901c86526020860195505b5093949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614db181602086016020860161581a565b601f01601f19169290920160200192915050565b600060018060a01b0380835116845280602084015116602085015250604082015160806040850152614dfa6080850182614bae565b905060608301518482036060860152614e138282614bae565b95945050505050565b60008251614e2e81846020870161581a565b9190910192915050565b6000808454614e468161592a565b60018281168015614e5e5760018114614e6f57614e9b565b60ff19841687528287019450614e9b565b8886526020808720875b85811015614e925781548a820152908401908201614e79565b50505082870194505b505050508351614eaf81836020880161581a565b01949350505050565b663337b932bb32b960c91b815260070190565b6001600160a01b0386811682528516602082015260a060408201819052600090614ef790830186614bae565b8281036060840152614f098186614bae565b90508281036080840152614f1d8185614d99565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090614f6390830184614d99565b979650505050505050565b60208152600061413d6020830184614bae565b604081526000614f946040830185614bae565b8281036020840152614e138185614bae565b600060a0820160a0835280885480835260c08501915089845260209250828420845b82811015614fe457815484529284019260019182019101614fc8565b50505083810382850152614ff88189614be8565b915050828103604084015261500d8187614be8565b60608401959095525050608001529392505050565b6020808252825182820181905260009190848201906040850190845b8181101561506057835163ffffffff168352928401929184019160010161503e565b50909695505050505050565b60208152600061413d6020830184614d99565b60006101208083526150938184018d614d99565b9050602060018060a01b03808d16828601526040818d1681870152818c16606087015263ffffffff8b16608087015261ffff9150818a1660a087015281891660c087015281881660e087015285840361010087015280840182885116855283880151828587015281815180845260608801915086830197508893505b8084101561513f57875180518716835287810151871688840152978701976001949094019392509084019061510f565b50809750505050505050509a9950505050505050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060a082018783526020878185015286604085015260018060a01b03808716606086015260a0608086015282865180855260c0870191508388019450855b81811015615325578551841683529484019491840191600101615307565b50909b9a5050505050505050505050565b60006101008b83528a6020840152806040840152893581840152506020890135601e198a3603018112615367578182fd5b890180356001600160401b0381111561537e578283fd5b8060051b8036038c1315615390578384fd5b604061012086015261014085018290526101606001600160fb1b038311156153b6578485fd5b816020850182880137818601935080840192508483528b60608701528a60808701528960a0870152808685030160c087015250506153f5818789614d70565b91505082810360e084015261540a8185614dc5565b9c9b505050505050505050505050565b6001600160801b038c811682528b811660208301528a16604082015263ffffffff8981166060830152888116608083015287811660a083015286811660c083015285811660e083015284166101008201528215156101208201526001600160a01b038216610140820152610160810161540a565b6000808335601e198436030181126154a4578283fd5b8301803591506001600160401b038211156154bd578283fd5b6020019150600681901b360382131561108357600080fd5b6000808335601e198436030181126154eb578283fd5b8301803591506001600160401b03821115615504578283fd5b6020019150600581901b360382131561108357600080fd5b6000808335601e19843603018112615532578283fd5b8301803591506001600160401b0382111561554b578283fd5b60200191503681900382131561108357600080fd5b60008235603e19833603018112614e2e578182fd5b60405161018081016001600160401b0381118282101715615598576155986159bc565b60405290565b60006001600160401b038211156155b7576155b76159bc565b5060051b60200190565b600082198211156155d4576155d46159a6565b500190565b6000826155f457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615613576156136159a6565b500290565b60008282101561562a5761562a6159a6565b500390565b5b81811015610ef95760008155600101615630565b600160401b831115615658576156586159bc565b8054838255808410156156b1578160005260206000206007850160031c8101601c8660021b16801561569b576000198083018054828460200360031b1c16815550505b506156ae6007840160031c83018261562f565b50505b506000818152602081208391805b868110156137ab576156f36156d3856159ec565b845463ffffffff600386901b81811b801990931693909116901b16178455565b602084019350600482019150601c82111561571357600091506001830192505b6001016156bf565b6001600160401b03831115615732576157326159bc565b61573c815461592a565b600080601f8611601f84118181171561575b5760008681526020902092505b801561578a57601f880160051c830160208910156157765750825b615788601f870160051c85018261562f565b505b5080600181146157be576000945087156157a5578387013594505b600188901b60001960038a901b1c198616178655615810565b601f198816945082845b868110156157e857888601358255602095860195600190920191016157c8565b50888610156158055760001960f88a60031b161c19858901351681555b5060018860011b0186555b5050505050505050565b60005b8381101561583557818101518382015260200161581d565b83811115615844576000848401525b50505050565b813561585581615d59565b815461ffff191661ffff82161782555060018082016020840135601e1985360301811261588157600080fd5b840180356001600160401b0381111561589957600080fd5b6020820191508060061b36038213156158b157600080fd5b600160401b8111156158c5576158c56159bc565b8254818455808210156158fa576000848152602081208381019083015b808210156158f657828255908701906158e2565b5050505b50600092835260208320925b818110156137ab576159188385615cea565b92840192604092909201918401615906565b600181811c9082168061593e57607f821691505b60208210811415610f5957634e487b7160e01b600052602260045260246000fd5b601f8201601f191681016001600160401b0381118282101715615984576159846159bc565b6040525050565b600060001982141561599f5761599f6159a6565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610d0981615d2e565b60008135610d0981615d59565b60008135610d0981615d69565b600060033d1115615a0e57600481823e5160e01c5b90565b600060443d1015615a1f5790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615a4e57505050505090565b8285019150815181811115615a665750505050505090565b843d8701016020828501011115615a805750505050505090565b615a8f6020828601018761595f565b509095945050505050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b615ac4828361551c565b615acf81838561571b565b5050615ae9615ae0602084016159d2565b60018301615a9a565b615b01615af8604084016159d2565b60028301615a9a565b615b19615b10606084016159d2565b60038301615a9a565b615b2660808301836154d5565b615b34818360048601615644565b505060058101615b60615b4960a085016159ec565b825463ffffffff191663ffffffff91909116178255565b615b8d615b6f60c085016159df565b825465ffff00000000191660209190911b65ffff0000000016178255565b615bbe615b9c60e085016159df565b825467ffff000000000000191660309190911b67ffff00000000000016178255565b615bef615bce61010085016159df565b825461ffff60401b191660409190911b69ffff000000000000000016178255565b50610ef9615c01610120840184615560565b6006830161584a565b8135615c1581615d59565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615c4157600080fd5b840180356001600160401b03811115615c5957600080fd5b6020820191508060061b3603821315615c7157600080fd5b600160401b811115615c8557615c856159bc565b825481845580821015615cba576000848152602081208381019083015b80821015615cb65782825590870190615ca2565b5050505b50600092835260208320925b818110156137ab57615cd88385615cea565b92840192604092909201918401615cc6565b8135615cf581615d59565b815461ffff191661ffff8216178255506020820135615d1381615d59565b815463ffff0000191660109190911b63ffff00001617905550565b6001600160a01b038116811461170457600080fd5b6001600160e01b03198116811461170457600080fd5b61ffff8116811461170457600080fd5b63ffffffff8116811461170457600080fdfea2646970667358221220caa72b60b00cd020d8050a12f1553066e3c14ed773dd3cba2949ae6d44eb243164736f6c63430008040033
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.