Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 17021397 | 597 days ago | IN | 0 ETH | 0.11415967 |
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.1 - 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); } // 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(); } _; } // OPTIONAL ROYALTY ENFORCEMENT WITH OPENSEA function enableRoyaltyEnforcement() external onlyOwner { if (options.royaltyEnforcementLocked) { revert LockedForever(); } _registerForOperatorFiltering(); options.royaltyEnforcementEnabled = true; } function disableRoyaltyEnforcement() external onlyOwner { if (options.royaltyEnforcementLocked) { revert LockedForever(); } options.royaltyEnforcementEnabled = false; } /// @notice the password is "forever" function lockRoyaltyEnforcement(string memory password) external onlyOwner { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } options.royaltyEnforcementLocked = true; } function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } function safeTransferFrom( address from, address to, uint256 tokenId, uint256 amount, bytes memory data ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, amount, data); } function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public override onlyAllowedOperator(from) { super.safeBatchTransferFrom(from, to, ids, amounts, data); } function _operatorFilteringEnabled() internal view override returns (bool) { return options.royaltyEnforcementEnabled; } //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.1 - 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 royaltyEnforcementEnabled; bool royaltyEnforcementLocked; 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": "0x3eb3e24cae6f1c587e8448fb64b87db4223d96e1" } } }
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":[],"name":"disableRoyaltyEnforcement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableRoyaltyEnforcement","outputs":[],"stateMutability":"nonpayable","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":"lockRoyaltyEnforcement","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":[{"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":"royaltyEnforcementEnabled","type":"bool"},{"internalType":"bool","name":"royaltyEnforcementLocked","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":"tokenId","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
608060405234801561001057600080fd5b50615f4580620000216000396000f3fe60806040526004361061034f5760003560e01c80636f33659f116101c6578063ac2aa9e4116100f7578063de6cd0db11610095578063ef8831721161006f578063ef88317214610c66578063f242432a14610c86578063f2fde38b14610ca6578063fd614f2a14610cc657600080fd5b8063de6cd0db14610bdd578063e985e9c514610bfd578063ead0055314610c4657600080fd5b8063c7494df7116100d1578063c7494df714610b5b578063ce216e2f14610b7b578063d5abeb0114610b9b578063d71d8d2314610bbd57600080fd5b8063ac2aa9e414610ab4578063b2938bd414610ac9578063bedcf00314610ae957600080fd5b806395d89b4111610164578063a15947c41161013e578063a15947c414610972578063a22cb46514610992578063a3edb86a146109b2578063a5aa4aa4146109f557600080fd5b806395d89b41146108e6578063978a4509146108fb5780639a7a973c1461094557600080fd5b80637b789d97116101a05780637b789d97146108805780637c5d0a08146108955780637ded1848146108b55780638da5cb5b146108c857600080fd5b80636f33659f14610821578063715018a61461084157806379502c551461085657600080fd5b80632a55205a116102a057806347286bc01161023e5780634e1273f4116102185780634e1273f4146107a15780635000d3d1146107ce57806355f804b3146107e15780635ecb16cd1461080157600080fd5b806347286bc0146107335780634a21a2df146107535780634bde38c81461076657600080fd5b806332f7c6d41161027a57806332f7c6d4146106be5780633ccfd60b146106de5780634331f639146106f357806343a11bc91461071357600080fd5b80632a55205a1461063f5780632eb2c2d61461067e57806331e1fdac1461069e57600080fd5b80631069143a1161030d5780631fff79b0116102e75780631fff79b01461050d57806321d5bf24146105205780632693ebf21461058757806327a59437146105a757600080fd5b80631069143a1461043057806310969523146104d857806318160ddd146104f857600080fd5b8062fdd58e1461035457806301ffc9a71461038757806306fdde03146103b75780630c6f910b146103d95780630e89341c146103fb5780630f7309e81461041b575b600080fd5b34801561036057600080fd5b5061037461036f366004614528565b610ce6565b6040519081526020015b60405180910390f35b34801561039357600080fd5b506103a76103a23660046148d2565b610d7e565b604051901515815260200161037e565b3480156103c357600080fd5b506103cc610d9e565b60405161037e9190615200565b3480156103e557600080fd5b506103f96103f4366004614cd1565b610e2d565b005b34801561040757600080fd5b506103cc610416366004614726565b610eab565b34801561042757600080fd5b506103cc610f30565b34801561043c57600080fd5b506101095461048f9060ff80821691610100810482169162010000820481169163010000008104821691600160201b8204811691600160281b8104821691600160301b8204811691600160381b90041688565b604080519815158952961515602089015294151595870195909552911515606086015215156080850152151560a084015290151560c0830152151560e08201526101000161037e565b3480156104e457600080fd5b506103f96104f336600461490a565b610f3e565b34801561050457600080fd5b50610374610f8a565b6103f961051b366004614bf7565b610fec565b34801561052c57600080fd5b5061056f61053b3660046143ad565b6001600160a01b03918216600090815260ff602090815260408083209390941682529190915220546001600160801b031690565b6040516001600160801b03909116815260200161037e565b34801561059357600080fd5b506103746105a2366004614726565b611003565b3480156105b357600080fd5b506106186105c236600461438a565b6040805180820190915260008082526020820152506001600160a01b0316600090815260fe60209081526040918290208251808401909352546001600160801b038082168452600160801b909104169082015290565b6040805182516001600160801b03908116825260209384015116928101929092520161037e565b34801561064b57600080fd5b5061065f61065a366004614d05565b611069565b604080516001600160a01b03909316835260208301919091520161037e565b34801561068a57600080fd5b506103f96106993660046143e5565b611117565b3480156106aa57600080fd5b506103f96106b936600461493c565b611151565b3480156106ca57600080fd5b506103f96106d936600461490a565b6115d3565b3480156106ea57600080fd5b506103f961165d565b3480156106ff57600080fd5b506103f961070e366004614553565b6116ce565b34801561071f57600080fd5b506103f961072e36600461487e565b611702565b34801561073f57600080fd5b506103f961074e36600461473e565b6119eb565b6103f9610761366004614acf565b611b3c565b34801561077257600080fd5b507386b82972282dd22348374bc63fd21620f7ed847b5b6040516001600160a01b03909116815260200161037e565b3480156107ad57600080fd5b506107c16107bc3660046145ba565b611b4c565b60405161037e9190615102565b6103f96107dc3660046149d7565b611cad565b3480156107ed57600080fd5b506103f96107fc36600461490a565b612178565b34801561080d57600080fd5b506103f961081c366004614580565b6121b9565b34801561082d57600080fd5b506103f961083c366004614d26565b612239565b34801561084d57600080fd5b506103f961225e565b34801561086257600080fd5b5061086b612272565b60405161037e99989796959493929190615213565b34801561088c57600080fd5b506103f96123df565b3480156108a157600080fd5b506103f96108b036600461490a565b612425565b6103f96108c3366004614b54565b6124aa565b3480156108d457600080fd5b506097546001600160a01b0316610789565b3480156108f257600080fd5b506103cc612ab1565b34801561090757600080fd5b5061056f61091636600461438a565b6001600160a01b0316600090815260ff602090815260408083208380529091529020546001600160801b031690565b34801561095157600080fd5b50610374610960366004614726565b600090815260fd602052604090205490565b34801561097e57600080fd5b506103f961098d36600461490a565b612abf565b34801561099e57600080fd5b506103f96109ad3660046144f4565b612b4c565b3480156109be57600080fd5b506103746109cd366004614528565b6001600160a01b0391909116600090815260fc60209081526040808320938352929052205490565b348015610a0157600080fd5b50610a9d610a10366004614726565b60fb6020526000908152604090208054600182015460028301546004909301546001600160801b0380841694600160801b948590048216949184169391820463ffffffff90811693600160a01b8404821693600160c01b8104831693600160e01b90910483169280821692600160201b830490911691600160401b900460ff16906001600160a01b03168b565b60405161037e9b9a999897969594939291906155ae565b348015610ac057600080fd5b506103f9612b78565b348015610ad557600080fd5b506103f9610ae43660046146b6565b612bcc565b348015610af557600080fd5b5060408051808201825260008082526020918201819052805260fe815281518083019092527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af546001600160801b038082168452600160801b9091041690820152610618565b348015610b6757600080fd5b506103f9610b7636600461490a565b612d6b565b348015610b8757600080fd5b506103f9610b9636600461490a565b612df4565b348015610ba757600080fd5b50610bb0612e7b565b60405161037e91906151b6565b348015610bc957600080fd5b506103f9610bd836600461438a565b612f03565b348015610be957600080fd5b506103f9610bf836600461490a565b612f5a565b348015610c0957600080fd5b506103a7610c183660046143ad565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b348015610c5257600080fd5b506103f9610c6136600461438a565b612fdd565b348015610c7257600080fd5b506103f9610c8136600461490a565b613034565b348015610c9257600080fd5b506103f9610ca136600461448e565b6130c0565b348015610cb257600080fd5b506103f9610cc136600461438a565b6130fa565b348015610cd257600080fd5b506103f9610ce1366004614c85565b613170565b60006001600160a01b038316610d565760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060009081526065602090815260408083206001600160a01b03949094168352929052205490565b6000610d8982613316565b80610d985750610d9882613366565b92915050565b61010a8054610dac90615abe565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd890615abe565b8015610e255780601f10610dfa57610100808354040283529160200191610e25565b820191906000526020600020905b815481529060010190602001808311610e0857829003601f168201915b505050505081565b610e3561338b565b6101095462010000900460ff1615610e605760405163249fab5d60e01b815260040160405180910390fd5b61138861ffff82161115610e87576040516306b7c75960e31b815260040160405180910390fd5b610106805461ffff909216600160201b0265ffff0000000019909216919091179055565b6060610eb6826133e5565b610ed357604051630a14c4b560e41b815260040160405180910390fd5b6101018054610ee190615abe565b15159050610efe5760405180602001604052806000815250610d98565b610101610f0a836133fb565b604051602001610f1b929190614fcc565b60405160208183030381529060405292915050565b61010c8054610dac90615abe565b610f4661338b565b61010954600160381b900460ff1615610f725760405163249fab5d60e01b815260040160405180910390fd5b8051610f869061010c906020840190613f7b565b5050565b600080805b61010054811015610fe6576101008181548110610fbc57634e487b7160e01b600052603260045260246000fd5b906000526020600020015482610fd29190615755565b915080610fde81615b1f565b915050610f8f565b50919050565b610ffb868633878787876124aa565b505050505050565b600061100e826133e5565b61102b57604051630a14c4b560e41b815260040160405180910390fd5b6101006110396001846157ac565b8154811061105757634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b600082815260ca602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916110de57506040805180820190915260c9546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906110fd906001600160601b03168761578d565b611107919061576d565b91519350909150505b9250929050565b846001600160a01b03811633146111445761010954600160281b900460ff16156111445761114433613449565b610ffb868686868661348d565b600054610100900460ff16158080156111715750600054600160ff909116105b8061118b5750303b15801561118b575060005460ff166001145b6111ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610d4d565b6000805460ff191660011790558015611211576000805461ff0019166101001790555b84516112259061010a906020880190613f7b565b50835161123a9061010b906020870190613f7b565b50611253604051806020016040528060008152506134d2565b61138861126660e0850160c08601614cd1565b61ffff16118061128b5750611388611285610100850160e08601614cd1565b61ffff16115b806112ab57506101f46112a5610100850160e08601614cd1565b61ffff16105b806112d657506113886112c26101208501856156f4565b6112d0906020810190614cd1565b61ffff16115b806112f9575060006112ee604085016020860161438a565b6001600160a01b0316145b80611317575061130f60c0840160a08501614d26565b63ffffffff16155b15611335576040516306b7c75960e31b815260040160405180910390fd5b60015b6113466101208501856156f4565b611354906020810190615622565b90508110156114a15761138861136e6101208601866156f4565b61137c906020810190615622565b8381811061139a57634e487b7160e01b600052603260045260246000fd5b90506040020160200160208101906113b29190614cd1565b61ffff16118061147157506113cb6101208501856156f4565b6113d9906020810190615622565b6113e46001846157ac565b81811061140157634e487b7160e01b600052603260045260246000fd5b6114179260206040909202019081019150614cd1565b61ffff166114296101208601866156f4565b611437906020810190615622565b8381811061145557634e487b7160e01b600052603260045260246000fd5b61146b9260206040909202019081019150614cd1565b61ffff16115b1561148f576040516306b7c75960e31b815260040160405180910390fd5b8061149981615b1f565b915050611338565b50826101016114b08282615c4e565b506114c090506080840184615669565b90506001600160401b038111156114e757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611510578160200160208202803683370190505b5080516115269161010091602090910190613fff565b5061152f613502565b610103546001600160a01b03161561156c576101035461010654611567916001600160a01b031690600160401b900461ffff166116ce565b611586565b61010654611586908390600160401b900461ffff166116ce565b80156115cc576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6115db61338b565b6040516020016115ea9061504c565b60405160208183030381529060405280519060200120816040516020016116119190614fb0565b604051602081830303815290604052805190602001201461164557604051635ee88f9760e01b815260040160405180910390fd5b50610109805464ff000000001916600160201b179055565b604080516001808252818301909252600091602080830190803683370190505090506000816000815181106116a257634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250506116cb816121b9565b50565b6116d661338b565b610106805461ffff60401b1916600160401b61ffff841690810291909117909155610f86908390613531565b61170a61338b565b604080516101808101909152806117246020840184614cb7565b6001600160801b0316815260209081019061174190840184614cb7565b6001600160801b0316815260200160006001600160801b031681526020018260200160208101906117729190614d26565b63ffffffff16815260200161178d6060840160408501614d26565b63ffffffff1681526020016117a86080840160608501614d26565b63ffffffff1681526020016117c360a0840160808501614d26565b63ffffffff168152600060208201526040016117e560c0840160a08501614d26565b63ffffffff16815260200161180060e0840160c0850161470c565b1515815260200161181460e0840184615669565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161185d6101208401610100850161438a565b6001600160a01b03169052600084815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b9115159190910217909255610140830151805161198e9260038501920190614039565b506101609190910151600490910180546001600160a01b0319166001600160a01b03909216919091179055604051829084907fe9a0c17645ed78ccc9996259f00297ffc75e6b9d22cd605ccc9992cc8ca3f4c190600090a3505050565b6119f361338b565b42816060015163ffffffff161015611a125763ffffffff421660608201525b600083815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b9115159190910217909255610140830151805184939261198e926003850192910190614039565b6115cc85853360008787876124aa565b60608151835114611bb15760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610d4d565b600083516001600160401b03811115611bda57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611c03578160200160208202803683370190505b50905060005b8451811015611ca557611c6a858281518110611c3557634e487b7160e01b600052603260045260246000fd5b6020026020010151858381518110611c5d57634e487b7160e01b600052603260045260246000fd5b6020026020010151610ce6565b828281518110611c8a57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152611c9e81615b1f565b9050611c09565b509392505050565b8588141580611cbc5750858414155b15611cda576040516306b7c75960e31b815260040160405180910390fd5b8935600090815260fb602052604090206002810154600160401b900460ff1680611d16575060028101546001600160201b90910463ffffffff16115b15611d3457604051630280e1e560e61b815260040160405180910390fd5b60408051608081018252600080825260208201526060918101829052818101919091526040518060800160405280611d746097546001600160a01b031690565b6001600160a01b03168152602001866001600160a01b031681526020018a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208a810282810182019093528a82529283019290918b918b918291850190849080828437600081840152601f19601f820116905080830192505050505050508152509050733eb3e24cae6f1c587e8448fb64b87db4223d96e1630e3deb14836101018f60fc60fd6101008b8b8a6040518a63ffffffff1660e01b8152600401611e5d999897969594939291906154ca565b60006040518083038186803b158015611e7557600080fd5b505af4158015611e89573d6000803e3d6000fd5b5050505060005b8a811015611fd4576060611f268d8d84818110611ebd57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611ed2919061438a565b8a8a85818110611ef257634e487b7160e01b600052603260045260246000fd5b905060200201358d8d86818110611f1957634e487b7160e01b600052603260045260246000fd5b905060200201358461362e565b8a8a83818110611f4657634e487b7160e01b600052603260045260246000fd5b9050602002013561010060018b8b86818110611f7257634e487b7160e01b600052603260045260246000fd5b90506020020135611f8391906157ac565b81548110611fa157634e487b7160e01b600052603260045260246000fd5b906000526020600020016000828254611fba9190615755565b90915550829150611fcc905081615b1f565b915050611e90565b506000805b89811015612027578a8a8281811061200157634e487b7160e01b600052603260045260246000fd5b90506020020135826120139190615755565b91508061201f81615b1f565b915050611fd9565b50600183015463ffffffff600160e01b82048116600160c01b90920416101561209a578060fc6000336001600160a01b03166001600160a01b0316815260200190815260200160002060008f60000135815260200190815260200160002060008282546120949190615755565b90915550505b600183015463ffffffff600160e01b909104811610156120da578c35600090815260fd6020526040812080548392906120d4908490615755565b90915550505b6040516329ba982960e21b815260048101849052610101602482015260fe604482015260ff60648201526001600160a01b038716608482015260a48101829052733eb3e24cae6f1c587e8448fb64b87db4223d96e19063a6ea60a49060c40160006040518083038186803b15801561215157600080fd5b505af4158015612165573d6000803e3d6000fd5b5050505050505050505050505050505050565b61218061338b565b6101095460ff16156121a55760405163249fab5d60e01b815260040160405180910390fd5b8051610f8690610101906020840190613f7b565b733eb3e24cae6f1c587e8448fb64b87db4223d96e16360f0e59661010160fe60ff6121ec6097546001600160a01b031690565b866040518663ffffffff1660e01b815260040161220d95949392919061545c565b60006040518083038186803b15801561222557600080fd5b505af41580156115cc573d6000803e3d6000fd5b61224161338b565b610106805463ffffffff191663ffffffff92909216919091179055565b61226661338b565b6122706000613744565b565b6101018054819061228290615abe565b80601f01602080910402602001604051908101604052809291908181526020018280546122ae90615abe565b80156122fb5780601f106122d0576101008083540402835291602001916122fb565b820191906000526020600020905b8154815290600101906020018083116122de57829003601f168201915b505050600184015460028501546003860154600587015460408051808201825260068a01805461ffff908116835260078c01805485516020828102820181019097528181529c9d6001600160a01b039a8b169d998b169c5097909916995063ffffffff861698600160201b8704831698600160301b8804841698600160401b90980490931696958086019392919060009084015b828210156123d2576000848152602090819020604080518082019091529084015461ffff808216835262010000909104168183015282526001909201910161238f565b5050505081525050905089565b6123e761338b565b61010954600160301b900460ff16156124135760405163249fab5d60e01b815260040160405180910390fd5b610109805465ff000000000019169055565b61242d61338b565b60405160200161243c9061504c565b60405160208183030381529060405280519060200120816040516020016124639190614fb0565b604051602081830303815290604052805190602001201461249757604051635ee88f9760e01b815260040160405180910390fd5b50610109805461ff001916610100179055565b8635600090815260fb6020526040902060028101546001600160201b90910463ffffffff1611156124f45760028101546124f190600160201b900463ffffffff168861578d565b96505b604080516080810182526000808252602082015260609181018290528181019190915260028201546060908190600160401b900460ff16156126f4576000733eb3e24cae6f1c587e8448fb64b87db4223d96e1635ec01e4d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561257657600080fd5b505af415801561258a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ae9190614ced565b9050733eb3e24cae6f1c587e8448fb64b87db4223d96e16310f11a15610100610101600401886003018f866040518663ffffffff1660e01b81526004016125f995949392919061513a565b60006040518083038186803b15801561261157600080fd5b505af4158015612625573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261264d919081019061461a565b925082516001600160401b0381111561267657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561269f578160200160208202803683370190505b50915060005b83518110156126ed5760018382815181106126d057634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806126e581615b1f565b9150506126a5565b5050612792565b6040805160018082528183019092529060208083019080368337019050509150878260008151811061273657634e487b7160e01b600052603260045260246000fd5b602090810291909101015260408051600180825281830190925290816020016020820280368337019050509050898160008151811061278557634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60405180608001604052806127af6097546001600160a01b031690565b6001600160a01b03168152602001886001600160a01b031681526020018281526020018381525092505050733eb3e24cae6f1c587e8448fb64b87db4223d96e1630e3deb14836101018c60fc60fd6101008b8b8a6040518a63ffffffff1660e01b8152600401612827999897969594939291906154ca565b60006040518083038186803b15801561283f57600080fd5b505af4158015612853573d6000803e3d6000fd5b5050505060005b8160600151518110156129835760606128cb898460600151848151811061289157634e487b7160e01b600052603260045260246000fd5b6020026020010151856040015185815181106128bd57634e487b7160e01b600052603260045260246000fd5b60200260200101518461362e565b826040015182815181106128ef57634e487b7160e01b600052603260045260246000fd5b602002602001015161010060018560600151858151811061292057634e487b7160e01b600052603260045260246000fd5b602002602001015161293291906157ac565b8154811061295057634e487b7160e01b600052603260045260246000fd5b9060005260206000200160008282546129699190615755565b9091555082915061297b905081615b1f565b91505061285a565b50600182015463ffffffff600160e01b82048116600160c01b9092041610156129d75733600090815260fc602090815260408083208c358452909152812080548a92906129d1908490615755565b90915550505b600182015463ffffffff600160e01b90910481161015612a17578835600090815260fd6020526040812080548a9290612a11908490615755565b90915550505b6040516329ba982960e21b815260048101839052610101602482015260fe604482015260ff60648201526001600160a01b038616608482015260a48101899052733eb3e24cae6f1c587e8448fb64b87db4223d96e19063a6ea60a49060c40160006040518083038186803b158015612a8e57600080fd5b505af4158015612aa2573d6000803e3d6000fd5b50505050505050505050505050565b61010b8054610dac90615abe565b612ac761338b565b604051602001612ad69061504c565b6040516020818303038152906040528051906020012081604051602001612afd9190614fb0565b6040516020818303038152906040528051906020012014612b3157604051635ee88f9760e01b815260040160405180910390fd5b50610109805467ff000000000000001916600160381b179055565b8161010954600160281b900460ff1615612b6957612b6981613449565b612b738383613796565b505050565b612b8061338b565b61010954600160301b900460ff1615612bac5760405163249fab5d60e01b815260040160405180910390fd5b612bb46137a1565b610109805465ff00000000001916600160281b179055565b612bd461338b565b604051602001612be39061504c565b6040516020818303038152906040528051906020012081604051602001612c0a9190614fb0565b6040516020818303038152906040528051906020012014612c3e57604051635ee88f9760e01b815260040160405180910390fd5b61010954610100900460ff1615612c685760405163249fab5d60e01b815260040160405180910390fd5b60005b61010054811015612d02576101008181548110612c9857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154838281518110612cc357634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161015612cf057604051638a164f6360e01b815260040160405180910390fd5b80612cfa81615b1f565b915050612c6b565b50610100545b8251811015612d5657610100805460018101825560009182527f45e010b9ae401e2eb71529478da8bd513a9bdc2d095a111e324f5b95c09ed87b015580612d4e81615b1f565b915050612d08565b508151612b7390610105906020850190614039565b612d7361338b565b604051602001612d829061504c565b6040516020818303038152906040528051906020012081604051602001612da99190614fb0565b6040516020818303038152906040528051906020012014612ddd57604051635ee88f9760e01b815260040160405180910390fd5b50610109805463ff00000019166301000000179055565b612dfc61338b565b604051602001612e0b9061504c565b6040516020818303038152906040528051906020012081604051602001612e329190614fb0565b6040516020818303038152906040528051906020012014612e6657604051635ee88f9760e01b815260040160405180910390fd5b50610109805462ff0000191662010000179055565b6060610101600401805480602002602001604051908101604052809291908181526020018280548015612ef957602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612ebc5790505b5050505050905090565b337386b82972282dd22348374bc63fd21620f7ed847b14612f375760405163016bdfed60e71b815260040160405180910390fd5b61010480546001600160a01b0319166001600160a01b0392909216919091179055565b612f6261338b565b604051602001612f719061504c565b6040516020818303038152906040528051906020012081604051602001612f989190614fb0565b6040516020818303038152906040528051906020012014612fcc57604051635ee88f9760e01b815260040160405180910390fd5b50610109805460ff19166001179055565b612fe561338b565b61010954600160201b900460ff16156130115760405163249fab5d60e01b815260040160405180910390fd5b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b61303c61338b565b60405160200161304b9061504c565b60405160208183030381529060405280519060200120816040516020016130729190614fb0565b60405160208183030381529060405280519060200120146130a657604051635ee88f9760e01b815260040160405180910390fd5b50610109805466ff0000000000001916600160301b179055565b846001600160a01b03811633146130ed5761010954600160281b900460ff16156130ed576130ed33613449565b610ffb86868686866137c0565b61310261338b565b6001600160a01b0381166131675760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d4d565b6116cb81613744565b61317861338b565b610109546301000000900460ff16156131a45760405163249fab5d60e01b815260040160405180910390fd5b6113886131b46020830183614cd1565b61ffff1611156131d7576040516306b7c75960e31b815260040160405180910390fd5b60015b6131e76020830183615622565b9050811015613307576113886132006020840184615622565b8381811061321e57634e487b7160e01b600052603260045260246000fd5b90506040020160200160208101906132369190614cd1565b61ffff1611806132d7575061324e6020830183615622565b6132596001846157ac565b81811061327657634e487b7160e01b600052603260045260246000fd5b61328c9260206040909202019081019150614cd1565b61ffff1661329d6020840184615622565b838181106132bb57634e487b7160e01b600052603260045260246000fd5b6132d19260206040909202019081019150614cd1565b61ffff16115b156132f5576040516306b7c75960e31b815260040160405180910390fd5b806132ff81615b1f565b9150506131da565b5080610107612b738282615d9e565b60006001600160e01b03198216636cdb3d1360e11b148061334757506001600160e01b031982166303a24d0760e21b145b80610d9857506301ffc9a760e01b6001600160e01b0319831614610d98565b60006001600160e01b0319821663152a902d60e11b1480610d985750610d9882613316565b6097546001600160a01b031633146122705760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d4d565b60008082118015610d9857505061010054101590565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061343257613437565b613415565b50819003601f19909101908152919050565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa613485573d6000803e3d6000fd5b6000603a5250565b6001600160a01b0385163314806134a957506134a98533610c18565b6134c55760405162461bcd60e51b8152600401610d4d90615334565b6115cc8585858585613805565b600054610100900460ff166134f95760405162461bcd60e51b8152600401610d4d90615411565b6116cb816139f9565b600054610100900460ff166135295760405162461bcd60e51b8152600401610d4d90615411565b612270613a29565b6127106001600160601b038216111561359f5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610d4d565b6001600160a01b0382166135f55760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610d4d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760c955565b6001600160a01b03841661368e5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610d4d565b33600061369a85613a59565b905060006136a785613a59565b905060008681526065602090815260408083206001600160a01b038b168452909152812080548792906136db908490615755565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461373b83600089898989613ab2565b50505050505050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b610f86338383613c1d565b612270733cc6cdda760b79bafa08df41ecfa224f810dceb66001613cfe565b6001600160a01b0385163314806137dc57506137dc8533610c18565b6137f85760405162461bcd60e51b8152600401610d4d90615334565b6115cc8585858585613d74565b81518351146138675760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610d4d565b6001600160a01b03841661388d5760405162461bcd60e51b8152600401610d4d90615382565b3360005b84518110156139935760008582815181106138bc57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008583815181106138e857634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526065835260408082206001600160a01b038e1683529093529190912054909150818110156139395760405162461bcd60e51b8152600401610d4d906153c7565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290613978908490615755565b925050819055505050508061398c90615b1f565b9050613891565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516139e3929190615115565b60405180910390a4610ffb818787878787613ea2565b600054610100900460ff16613a205760405162461bcd60e51b8152600401610d4d90615411565b6116cb81613f6c565b600054610100900460ff16613a505760405162461bcd60e51b8152600401610d4d90615411565b61227033613744565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613aa157634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b15610ffb5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613af690899089908890889088906004016150bd565b602060405180830381600087803b158015613b1057600080fd5b505af1925050508015613b40575060408051601f3d908101601f19168201909252613b3d918101906148ee565b60015b613bed57613b4c615b8d565b806308c379a01415613b865750613b61615ba5565b80613b6c5750613b88565b8060405162461bcd60e51b8152600401610d4d9190615200565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610d4d565b6001600160e01b0319811663f23a6e6160e01b1461373b5760405162461bcd60e51b8152600401610d4d906152ec565b816001600160a01b0316836001600160a01b03161415613c915760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610d4d565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0390911690637d3e3dbe81613d2b5782613d245750634420e486613d2b565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af1613d6a578060005160e01c1415613d6a57600080fd5b5060006024525050565b6001600160a01b038416613d9a5760405162461bcd60e51b8152600401610d4d90615382565b336000613da685613a59565b90506000613db385613a59565b905060008681526065602090815260408083206001600160a01b038c16845290915290205485811015613df85760405162461bcd60e51b8152600401610d4d906153c7565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290613e37908490615755565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613e97848a8a8a8a8a613ab2565b505050505050505050565b6001600160a01b0384163b15610ffb5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613ee6908990899088908890889060040161505f565b602060405180830381600087803b158015613f0057600080fd5b505af1925050508015613f30575060408051601f3d908101601f19168201909252613f2d918101906148ee565b60015b613f3c57613b4c615b8d565b6001600160e01b0319811663bc197c8160e01b1461373b5760405162461bcd60e51b8152600401610d4d906152ec565b8051610f869060679060208401905b828054613f8790615abe565b90600052602060002090601f016020900481019282613fa95760008555613fef565b82601f10613fc257805160ff1916838001178555613fef565b82800160010185558215613fef579182015b82811115613fef578251825591602001919060010190613fd4565b50613ffb9291506140df565b5090565b828054828255906000526020600020908101928215613fef5791602002820182811115613fef578251825591602001919060010190613fd4565b82805482825590600052602060002090600701600890048101928215613fef5791602002820160005b838211156140a657835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302614062565b80156140d65782816101000a81549063ffffffff02191690556004016020816003010492830192600103026140a6565b5050613ffb9291505b5b80821115613ffb57600081556001016140e0565b80356140ff81615ec2565b919050565b60008083601f840112614115578182fd5b5081356001600160401b0381111561412b578182fd5b6020830191508360208260051b850101111561111057600080fd5b600082601f830112614156578081fd5b8135602061416382615732565b6040516141708282615af3565b8381528281019150858301600585901b8701840188101561418f578586fd5b855b858110156141b65781356141a481615ec2565b84529284019290840190600101614191565b5090979650505050505050565b600082601f8301126141d3578081fd5b813560206141e082615732565b6040516141ed8282615af3565b8381528281019150858301600585901b8701840188101561420c578586fd5b855b858110156141b65781358452928401929084019060010161420e565b600082601f83011261423a578081fd5b8135602061424782615732565b6040516142548282615af3565b8381528281019150858301600585901b87018401881015614273578586fd5b855b858110156141b657813561428881615efd565b84529284019290840190600101614275565b803580151581146140ff57600080fd5b60008083601f8401126142bb578182fd5b5081356001600160401b038111156142d1578182fd5b60208301915083602082850101111561111057600080fd5b600082601f8301126142f9578081fd5b81356001600160401b0381111561431257614312615b50565b604051614329601f8301601f191660200182615af3565b81815284602083860101111561433d578283fd5b816020850160208301379081016020019190915292915050565b600060408284031215610fe6578081fd5b80356001600160801b03811681146140ff57600080fd5b80356140ff81615efd565b60006020828403121561439b578081fd5b81356143a681615ec2565b9392505050565b600080604083850312156143bf578081fd5b82356143ca81615ec2565b915060208301356143da81615ec2565b809150509250929050565b600080600080600060a086880312156143fc578081fd5b853561440781615ec2565b9450602086013561441781615ec2565b935060408601356001600160401b0380821115614432578283fd5b61443e89838a016141c3565b94506060880135915080821115614453578283fd5b61445f89838a016141c3565b93506080880135915080821115614474578283fd5b50614481888289016142e9565b9150509295509295909350565b600080600080600060a086880312156144a5578283fd5b85356144b081615ec2565b945060208601356144c081615ec2565b9350604086013592506060860135915060808601356001600160401b038111156144e8578182fd5b614481888289016142e9565b60008060408385031215614506578182fd5b823561451181615ec2565b915061451f6020840161429a565b90509250929050565b6000806040838503121561453a578182fd5b823561454581615ec2565b946020939093013593505050565b60008060408385031215614565578182fd5b823561457081615ec2565b915060208301356143da81615eed565b600060208284031215614591578081fd5b81356001600160401b038111156145a6578182fd5b6145b284828501614146565b949350505050565b600080604083850312156145cc578182fd5b82356001600160401b03808211156145e2578384fd5b6145ee86838701614146565b93506020850135915080821115614603578283fd5b50614610858286016141c3565b9150509250929050565b6000602080838503121561462c578182fd5b82516001600160401b03811115614641578283fd5b8301601f81018513614651578283fd5b805161465c81615732565b6040516146698282615af3565b8281528481019150838501600584901b85018601891015614688578687fd5b8694505b838510156146aa57805183526001949094019391850191850161468c565b50979650505050505050565b600080604083850312156146c8578182fd5b82356001600160401b03808211156146de578384fd5b6146ea8683870161422a565b935060208501359150808211156146ff578283fd5b50614610858286016142e9565b60006020828403121561471d578081fd5b6143a68261429a565b600060208284031215614737578081fd5b5035919050565b600080600060608486031215614752578081fd5b833592506020840135915060408401356001600160401b0380821115614776578283fd5b90850190610180828803121561478a578283fd5b614792615709565b61479b83614368565b81526147a960208401614368565b60208201526147ba60408401614368565b60408201526147cb6060840161437f565b60608201526147dc6080840161437f565b60808201526147ed60a0840161437f565b60a08201526147fe60c0840161437f565b60c082015261480f60e0840161437f565b60e082015261010061482281850161437f565b9082015261012061483484820161429a565b90820152610140838101358381111561484b578586fd5b6148578a82870161422a565b828401525050610160915061486d8284016140f4565b828201528093505050509250925092565b600080600060608486031215614892578081fd5b833592506020840135915060408401356001600160401b038111156148b5578182fd5b840161012081870312156148c7578182fd5b809150509250925092565b6000602082840312156148e3578081fd5b81356143a681615ed7565b6000602082840312156148ff578081fd5b81516143a681615ed7565b60006020828403121561491b578081fd5b81356001600160401b03811115614930578182fd5b6145b2848285016142e9565b60008060008060808587031215614951578182fd5b84356001600160401b0380821115614967578384fd5b614973888389016142e9565b95506020870135915080821115614988578384fd5b614994888389016142e9565b945060408701359150808211156149a9578384fd5b50850161014081880312156149bc578283fd5b915060608501356149cc81615ec2565b939692955090935050565b60008060008060008060008060008060c08b8d0312156149f5578788fd5b8a356001600160401b0380821115614a0b57898afd5b614a178e838f01614357565b9b5060208d0135915080821115614a2c57898afd5b614a388e838f01614104565b909b50995060408d0135915080821115614a50578687fd5b614a5c8e838f01614104565b909950975060608d0135915080821115614a74578687fd5b614a808e838f01614104565b9097509550859150614a9460808e016140f4565b945060a08d0135915080821115614aa9578384fd5b50614ab68d828e016142aa565b915080935050809150509295989b9194979a5092959850565b600080600080600060808688031215614ae6578283fd5b85356001600160401b0380821115614afc578485fd5b614b0889838a01614357565b96506020880135955060408801359150614b2182615ec2565b90935060608701359080821115614b36578283fd5b50614b43888289016142aa565b969995985093965092949392505050565b600080600080600080600060c0888a031215614b6e578081fd5b87356001600160401b0380821115614b84578283fd5b614b908b838c01614357565b985060208a0135975060408a01359150614ba982615ec2565b90955060608901359450608089013590614bc282615ec2565b90935060a08901359080821115614bd7578283fd5b50614be48a828b016142aa565b989b979a50959850939692959293505050565b60008060008060008060a08789031215614c0f578384fd5b86356001600160401b0380821115614c25578586fd5b614c318a838b01614357565b9750602089013596506040890135955060608901359150614c5182615ec2565b90935060808801359080821115614c66578384fd5b50614c7389828a016142aa565b979a9699509497509295939492505050565b600060208284031215614c96578081fd5b81356001600160401b03811115614cab578182fd5b6145b284828501614357565b600060208284031215614cc8578081fd5b6143a682614368565b600060208284031215614ce2578081fd5b81356143a681615eed565b600060208284031215614cfe578081fd5b5051919050565b60008060408385031215614d17578182fd5b50508035926020909101359150565b600060208284031215614d37578081fd5b81356143a681615efd565b6000815180845260208085019450808401835b83811015614d7157815187529582019590820190600101614d55565b509495945050505050565b805480835260008281526020808220940193909190825b82600782011015614e0b57815463ffffffff8082168852602082811c821690890152604082811c821690890152606082811c821690890152608082811c82169089015260a082811c82169089015260c082811c9091169088015260e090811c9087015261010090950194600190910190600801614d93565b90549082811015614e295763ffffffff821686526020909501946001015b82811015614e4957602082901c63ffffffff168652602095909501946001015b82811015614e685763ffffffff604083901c1686526020909501946001015b82811015614e875763ffffffff606083901c1686526020909501946001015b82811015614ea65763ffffffff608083901c1686526020909501946001015b82811015614ec55763ffffffff60a083901c1686526020909501946001015b82811015614ee45763ffffffff60c083901c1686526020909501946001015b82811015614efa5760e082901c86526020860195505b5093949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614f458160208601602086016159ae565b601f01601f19169290920160200192915050565b600060018060a01b0380835116845280602084015116602085015250604082015160806040850152614f8e6080850182614d42565b905060608301518482036060860152614fa78282614d42565b95945050505050565b60008251614fc28184602087016159ae565b9190910192915050565b6000808454614fda81615abe565b60018281168015614ff257600181146150035761502f565b60ff1984168752828701945061502f565b8886526020808720875b858110156150265781548a82015290840190820161500d565b50505082870194505b5050505083516150438183602088016159ae565b01949350505050565b663337b932bb32b960c91b815260070190565b6001600160a01b0386811682528516602082015260a06040820181905260009061508b90830186614d42565b828103606084015261509d8186614d42565b905082810360808401526150b18185614f2d565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906150f790830184614f2d565b979650505050505050565b6020815260006143a66020830184614d42565b6040815260006151286040830185614d42565b8281036020840152614fa78185614d42565b600060a0820160a0835280885480835260c08501915089845260209250828420845b828110156151785781548452928401926001918201910161515c565b5050508381038285015261518c8189614d7c565b91505082810360408401526151a18187614d7c565b60608401959095525050608001529392505050565b6020808252825182820181905260009190848201906040850190845b818110156151f457835163ffffffff16835292840192918401916001016151d2565b50909695505050505050565b6020815260006143a66020830184614f2d565b60006101208083526152278184018d614f2d565b9050602060018060a01b03808d16828601526040818d1681870152818c16606087015263ffffffff8b16608087015261ffff9150818a1660a087015281891660c087015281881660e087015285840361010087015280840182885116855283880151828587015281815180845260608801915086830197508893505b808410156152d35787518051871683528781015187168884015297870197600194909401939250908401906152a3565b50809750505050505050509a9950505050505050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060a082018783526020878185015286604085015260018060a01b03808716606086015260a0608086015282865180855260c0870191508388019450855b818110156154b957855184168352948401949184019160010161549b565b50909b9a5050505050505050505050565b60006101008b83528a6020840152806040840152893581840152506020890135601e198a36030181126154fb578182fd5b890180356001600160401b03811115615512578283fd5b8060051b8036038c1315615524578384fd5b604061012086015261014085018290526101606001600160fb1b0383111561554a578485fd5b816020850182880137818601935080840192508483528b60608701528a60808701528960a0870152808685030160c08701525050615589818789614f04565b91505082810360e084015261559e8185614f59565b9c9b505050505050505050505050565b6001600160801b038c811682528b811660208301528a16604082015263ffffffff8981166060830152888116608083015287811660a083015286811660c083015285811660e083015284166101008201528215156101208201526001600160a01b038216610140820152610160810161559e565b6000808335601e19843603018112615638578283fd5b8301803591506001600160401b03821115615651578283fd5b6020019150600681901b360382131561111057600080fd5b6000808335601e1984360301811261567f578283fd5b8301803591506001600160401b03821115615698578283fd5b6020019150600581901b360382131561111057600080fd5b6000808335601e198436030181126156c6578283fd5b8301803591506001600160401b038211156156df578283fd5b60200191503681900382131561111057600080fd5b60008235603e19833603018112614fc2578182fd5b60405161018081016001600160401b038111828210171561572c5761572c615b50565b60405290565b60006001600160401b0382111561574b5761574b615b50565b5060051b60200190565b6000821982111561576857615768615b3a565b500190565b60008261578857634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156157a7576157a7615b3a565b500290565b6000828210156157be576157be615b3a565b500390565b5b81811015610f8657600081556001016157c4565b600160401b8311156157ec576157ec615b50565b805483825580841015615845578160005260206000206007850160031c8101601c8660021b16801561582f576000198083018054828460200360031b1c16815550505b506158426007840160031c8301826157c3565b50505b506000818152602081208391805b8681101561373b5761588761586785615b80565b845463ffffffff600386901b81811b801990931693909116901b16178455565b602084019350600482019150601c8211156158a757600091506001830192505b600101615853565b6001600160401b038311156158c6576158c6615b50565b6158d08154615abe565b600080601f8611601f8411818117156158ef5760008681526020902092505b801561591e57601f880160051c8301602089101561590a5750825b61591c601f870160051c8501826157c3565b505b50806001811461595257600094508715615939578387013594505b600188901b60001960038a901b1c1986161786556159a4565b601f198816945082845b8681101561597c578886013582556020958601956001909201910161595c565b50888610156159995760001960f88a60031b161c19858901351681555b5060018860011b0186555b5050505050505050565b60005b838110156159c95781810151838201526020016159b1565b838111156159d8576000848401525b50505050565b81356159e981615eed565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615a1557600080fd5b840180356001600160401b03811115615a2d57600080fd5b6020820191508060061b3603821315615a4557600080fd5b600160401b811115615a5957615a59615b50565b825481845580821015615a8e576000848152602081208381019083015b80821015615a8a5782825590870190615a76565b5050505b50600092835260208320925b8181101561373b57615aac8385615e7e565b92840192604092909201918401615a9a565b600181811c90821680615ad257607f821691505b60208210811415610fe657634e487b7160e01b600052602260045260246000fd5b601f8201601f191681016001600160401b0381118282101715615b1857615b18615b50565b6040525050565b6000600019821415615b3357615b33615b3a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610d9881615ec2565b60008135610d9881615eed565b60008135610d9881615efd565b600060033d1115615ba257600481823e5160e01c5b90565b600060443d1015615bb35790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615be257505050505090565b8285019150815181811115615bfa5750505050505090565b843d8701016020828501011115615c145750505050505090565b615c2360208286010187615af3565b509095945050505050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b615c5882836156b0565b615c638183856158af565b5050615c7d615c7460208401615b66565b60018301615c2e565b615c95615c8c60408401615b66565b60028301615c2e565b615cad615ca460608401615b66565b60038301615c2e565b615cba6080830183615669565b615cc88183600486016157d8565b505060058101615cf4615cdd60a08501615b80565b825463ffffffff191663ffffffff91909116178255565b615d21615d0360c08501615b73565b825465ffff00000000191660209190911b65ffff0000000016178255565b615d52615d3060e08501615b73565b825467ffff000000000000191660309190911b67ffff00000000000016178255565b615d83615d626101008501615b73565b825461ffff60401b191660409190911b69ffff000000000000000016178255565b50610f86615d956101208401846156f4565b600683016159de565b8135615da981615eed565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615dd557600080fd5b840180356001600160401b03811115615ded57600080fd5b6020820191508060061b3603821315615e0557600080fd5b600160401b811115615e1957615e19615b50565b825481845580821015615e4e576000848152602081208381019083015b80821015615e4a5782825590870190615e36565b5050505b50600092835260208320925b8181101561373b57615e6c8385615e7e565b92840192604092909201918401615e5a565b8135615e8981615eed565b815461ffff191661ffff8216178255506020820135615ea781615eed565b815463ffff0000191660109190911b63ffff00001617905550565b6001600160a01b03811681146116cb57600080fd5b6001600160e01b0319811681146116cb57600080fd5b61ffff811681146116cb57600080fd5b63ffffffff811681146116cb57600080fdfea2646970667358221220dc567c006e00992ae4728b07f5875afa89a591ed397cf74afade23a7ff3e0cd364736f6c63430008040033
Deployed Bytecode
0x60806040526004361061034f5760003560e01c80636f33659f116101c6578063ac2aa9e4116100f7578063de6cd0db11610095578063ef8831721161006f578063ef88317214610c66578063f242432a14610c86578063f2fde38b14610ca6578063fd614f2a14610cc657600080fd5b8063de6cd0db14610bdd578063e985e9c514610bfd578063ead0055314610c4657600080fd5b8063c7494df7116100d1578063c7494df714610b5b578063ce216e2f14610b7b578063d5abeb0114610b9b578063d71d8d2314610bbd57600080fd5b8063ac2aa9e414610ab4578063b2938bd414610ac9578063bedcf00314610ae957600080fd5b806395d89b4111610164578063a15947c41161013e578063a15947c414610972578063a22cb46514610992578063a3edb86a146109b2578063a5aa4aa4146109f557600080fd5b806395d89b41146108e6578063978a4509146108fb5780639a7a973c1461094557600080fd5b80637b789d97116101a05780637b789d97146108805780637c5d0a08146108955780637ded1848146108b55780638da5cb5b146108c857600080fd5b80636f33659f14610821578063715018a61461084157806379502c551461085657600080fd5b80632a55205a116102a057806347286bc01161023e5780634e1273f4116102185780634e1273f4146107a15780635000d3d1146107ce57806355f804b3146107e15780635ecb16cd1461080157600080fd5b806347286bc0146107335780634a21a2df146107535780634bde38c81461076657600080fd5b806332f7c6d41161027a57806332f7c6d4146106be5780633ccfd60b146106de5780634331f639146106f357806343a11bc91461071357600080fd5b80632a55205a1461063f5780632eb2c2d61461067e57806331e1fdac1461069e57600080fd5b80631069143a1161030d5780631fff79b0116102e75780631fff79b01461050d57806321d5bf24146105205780632693ebf21461058757806327a59437146105a757600080fd5b80631069143a1461043057806310969523146104d857806318160ddd146104f857600080fd5b8062fdd58e1461035457806301ffc9a71461038757806306fdde03146103b75780630c6f910b146103d95780630e89341c146103fb5780630f7309e81461041b575b600080fd5b34801561036057600080fd5b5061037461036f366004614528565b610ce6565b6040519081526020015b60405180910390f35b34801561039357600080fd5b506103a76103a23660046148d2565b610d7e565b604051901515815260200161037e565b3480156103c357600080fd5b506103cc610d9e565b60405161037e9190615200565b3480156103e557600080fd5b506103f96103f4366004614cd1565b610e2d565b005b34801561040757600080fd5b506103cc610416366004614726565b610eab565b34801561042757600080fd5b506103cc610f30565b34801561043c57600080fd5b506101095461048f9060ff80821691610100810482169162010000820481169163010000008104821691600160201b8204811691600160281b8104821691600160301b8204811691600160381b90041688565b604080519815158952961515602089015294151595870195909552911515606086015215156080850152151560a084015290151560c0830152151560e08201526101000161037e565b3480156104e457600080fd5b506103f96104f336600461490a565b610f3e565b34801561050457600080fd5b50610374610f8a565b6103f961051b366004614bf7565b610fec565b34801561052c57600080fd5b5061056f61053b3660046143ad565b6001600160a01b03918216600090815260ff602090815260408083209390941682529190915220546001600160801b031690565b6040516001600160801b03909116815260200161037e565b34801561059357600080fd5b506103746105a2366004614726565b611003565b3480156105b357600080fd5b506106186105c236600461438a565b6040805180820190915260008082526020820152506001600160a01b0316600090815260fe60209081526040918290208251808401909352546001600160801b038082168452600160801b909104169082015290565b6040805182516001600160801b03908116825260209384015116928101929092520161037e565b34801561064b57600080fd5b5061065f61065a366004614d05565b611069565b604080516001600160a01b03909316835260208301919091520161037e565b34801561068a57600080fd5b506103f96106993660046143e5565b611117565b3480156106aa57600080fd5b506103f96106b936600461493c565b611151565b3480156106ca57600080fd5b506103f96106d936600461490a565b6115d3565b3480156106ea57600080fd5b506103f961165d565b3480156106ff57600080fd5b506103f961070e366004614553565b6116ce565b34801561071f57600080fd5b506103f961072e36600461487e565b611702565b34801561073f57600080fd5b506103f961074e36600461473e565b6119eb565b6103f9610761366004614acf565b611b3c565b34801561077257600080fd5b507386b82972282dd22348374bc63fd21620f7ed847b5b6040516001600160a01b03909116815260200161037e565b3480156107ad57600080fd5b506107c16107bc3660046145ba565b611b4c565b60405161037e9190615102565b6103f96107dc3660046149d7565b611cad565b3480156107ed57600080fd5b506103f96107fc36600461490a565b612178565b34801561080d57600080fd5b506103f961081c366004614580565b6121b9565b34801561082d57600080fd5b506103f961083c366004614d26565b612239565b34801561084d57600080fd5b506103f961225e565b34801561086257600080fd5b5061086b612272565b60405161037e99989796959493929190615213565b34801561088c57600080fd5b506103f96123df565b3480156108a157600080fd5b506103f96108b036600461490a565b612425565b6103f96108c3366004614b54565b6124aa565b3480156108d457600080fd5b506097546001600160a01b0316610789565b3480156108f257600080fd5b506103cc612ab1565b34801561090757600080fd5b5061056f61091636600461438a565b6001600160a01b0316600090815260ff602090815260408083208380529091529020546001600160801b031690565b34801561095157600080fd5b50610374610960366004614726565b600090815260fd602052604090205490565b34801561097e57600080fd5b506103f961098d36600461490a565b612abf565b34801561099e57600080fd5b506103f96109ad3660046144f4565b612b4c565b3480156109be57600080fd5b506103746109cd366004614528565b6001600160a01b0391909116600090815260fc60209081526040808320938352929052205490565b348015610a0157600080fd5b50610a9d610a10366004614726565b60fb6020526000908152604090208054600182015460028301546004909301546001600160801b0380841694600160801b948590048216949184169391820463ffffffff90811693600160a01b8404821693600160c01b8104831693600160e01b90910483169280821692600160201b830490911691600160401b900460ff16906001600160a01b03168b565b60405161037e9b9a999897969594939291906155ae565b348015610ac057600080fd5b506103f9612b78565b348015610ad557600080fd5b506103f9610ae43660046146b6565b612bcc565b348015610af557600080fd5b5060408051808201825260008082526020918201819052805260fe815281518083019092527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af546001600160801b038082168452600160801b9091041690820152610618565b348015610b6757600080fd5b506103f9610b7636600461490a565b612d6b565b348015610b8757600080fd5b506103f9610b9636600461490a565b612df4565b348015610ba757600080fd5b50610bb0612e7b565b60405161037e91906151b6565b348015610bc957600080fd5b506103f9610bd836600461438a565b612f03565b348015610be957600080fd5b506103f9610bf836600461490a565b612f5a565b348015610c0957600080fd5b506103a7610c183660046143ad565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b348015610c5257600080fd5b506103f9610c6136600461438a565b612fdd565b348015610c7257600080fd5b506103f9610c8136600461490a565b613034565b348015610c9257600080fd5b506103f9610ca136600461448e565b6130c0565b348015610cb257600080fd5b506103f9610cc136600461438a565b6130fa565b348015610cd257600080fd5b506103f9610ce1366004614c85565b613170565b60006001600160a01b038316610d565760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060009081526065602090815260408083206001600160a01b03949094168352929052205490565b6000610d8982613316565b80610d985750610d9882613366565b92915050565b61010a8054610dac90615abe565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd890615abe565b8015610e255780601f10610dfa57610100808354040283529160200191610e25565b820191906000526020600020905b815481529060010190602001808311610e0857829003601f168201915b505050505081565b610e3561338b565b6101095462010000900460ff1615610e605760405163249fab5d60e01b815260040160405180910390fd5b61138861ffff82161115610e87576040516306b7c75960e31b815260040160405180910390fd5b610106805461ffff909216600160201b0265ffff0000000019909216919091179055565b6060610eb6826133e5565b610ed357604051630a14c4b560e41b815260040160405180910390fd5b6101018054610ee190615abe565b15159050610efe5760405180602001604052806000815250610d98565b610101610f0a836133fb565b604051602001610f1b929190614fcc565b60405160208183030381529060405292915050565b61010c8054610dac90615abe565b610f4661338b565b61010954600160381b900460ff1615610f725760405163249fab5d60e01b815260040160405180910390fd5b8051610f869061010c906020840190613f7b565b5050565b600080805b61010054811015610fe6576101008181548110610fbc57634e487b7160e01b600052603260045260246000fd5b906000526020600020015482610fd29190615755565b915080610fde81615b1f565b915050610f8f565b50919050565b610ffb868633878787876124aa565b505050505050565b600061100e826133e5565b61102b57604051630a14c4b560e41b815260040160405180910390fd5b6101006110396001846157ac565b8154811061105757634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b600082815260ca602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916110de57506040805180820190915260c9546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906110fd906001600160601b03168761578d565b611107919061576d565b91519350909150505b9250929050565b846001600160a01b03811633146111445761010954600160281b900460ff16156111445761114433613449565b610ffb868686868661348d565b600054610100900460ff16158080156111715750600054600160ff909116105b8061118b5750303b15801561118b575060005460ff166001145b6111ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610d4d565b6000805460ff191660011790558015611211576000805461ff0019166101001790555b84516112259061010a906020880190613f7b565b50835161123a9061010b906020870190613f7b565b50611253604051806020016040528060008152506134d2565b61138861126660e0850160c08601614cd1565b61ffff16118061128b5750611388611285610100850160e08601614cd1565b61ffff16115b806112ab57506101f46112a5610100850160e08601614cd1565b61ffff16105b806112d657506113886112c26101208501856156f4565b6112d0906020810190614cd1565b61ffff16115b806112f9575060006112ee604085016020860161438a565b6001600160a01b0316145b80611317575061130f60c0840160a08501614d26565b63ffffffff16155b15611335576040516306b7c75960e31b815260040160405180910390fd5b60015b6113466101208501856156f4565b611354906020810190615622565b90508110156114a15761138861136e6101208601866156f4565b61137c906020810190615622565b8381811061139a57634e487b7160e01b600052603260045260246000fd5b90506040020160200160208101906113b29190614cd1565b61ffff16118061147157506113cb6101208501856156f4565b6113d9906020810190615622565b6113e46001846157ac565b81811061140157634e487b7160e01b600052603260045260246000fd5b6114179260206040909202019081019150614cd1565b61ffff166114296101208601866156f4565b611437906020810190615622565b8381811061145557634e487b7160e01b600052603260045260246000fd5b61146b9260206040909202019081019150614cd1565b61ffff16115b1561148f576040516306b7c75960e31b815260040160405180910390fd5b8061149981615b1f565b915050611338565b50826101016114b08282615c4e565b506114c090506080840184615669565b90506001600160401b038111156114e757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611510578160200160208202803683370190505b5080516115269161010091602090910190613fff565b5061152f613502565b610103546001600160a01b03161561156c576101035461010654611567916001600160a01b031690600160401b900461ffff166116ce565b611586565b61010654611586908390600160401b900461ffff166116ce565b80156115cc576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6115db61338b565b6040516020016115ea9061504c565b60405160208183030381529060405280519060200120816040516020016116119190614fb0565b604051602081830303815290604052805190602001201461164557604051635ee88f9760e01b815260040160405180910390fd5b50610109805464ff000000001916600160201b179055565b604080516001808252818301909252600091602080830190803683370190505090506000816000815181106116a257634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250506116cb816121b9565b50565b6116d661338b565b610106805461ffff60401b1916600160401b61ffff841690810291909117909155610f86908390613531565b61170a61338b565b604080516101808101909152806117246020840184614cb7565b6001600160801b0316815260209081019061174190840184614cb7565b6001600160801b0316815260200160006001600160801b031681526020018260200160208101906117729190614d26565b63ffffffff16815260200161178d6060840160408501614d26565b63ffffffff1681526020016117a86080840160608501614d26565b63ffffffff1681526020016117c360a0840160808501614d26565b63ffffffff168152600060208201526040016117e560c0840160a08501614d26565b63ffffffff16815260200161180060e0840160c0850161470c565b1515815260200161181460e0840184615669565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161185d6101208401610100850161438a565b6001600160a01b03169052600084815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b9115159190910217909255610140830151805161198e9260038501920190614039565b506101609190910151600490910180546001600160a01b0319166001600160a01b03909216919091179055604051829084907fe9a0c17645ed78ccc9996259f00297ffc75e6b9d22cd605ccc9992cc8ca3f4c190600090a3505050565b6119f361338b565b42816060015163ffffffff161015611a125763ffffffff421660608201525b600083815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b91909616029490941760ff60401b1916600160401b9115159190910217909255610140830151805184939261198e926003850192910190614039565b6115cc85853360008787876124aa565b60608151835114611bb15760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610d4d565b600083516001600160401b03811115611bda57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611c03578160200160208202803683370190505b50905060005b8451811015611ca557611c6a858281518110611c3557634e487b7160e01b600052603260045260246000fd5b6020026020010151858381518110611c5d57634e487b7160e01b600052603260045260246000fd5b6020026020010151610ce6565b828281518110611c8a57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152611c9e81615b1f565b9050611c09565b509392505050565b8588141580611cbc5750858414155b15611cda576040516306b7c75960e31b815260040160405180910390fd5b8935600090815260fb602052604090206002810154600160401b900460ff1680611d16575060028101546001600160201b90910463ffffffff16115b15611d3457604051630280e1e560e61b815260040160405180910390fd5b60408051608081018252600080825260208201526060918101829052818101919091526040518060800160405280611d746097546001600160a01b031690565b6001600160a01b03168152602001866001600160a01b031681526020018a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208a810282810182019093528a82529283019290918b918b918291850190849080828437600081840152601f19601f820116905080830192505050505050508152509050733eb3e24cae6f1c587e8448fb64b87db4223d96e1630e3deb14836101018f60fc60fd6101008b8b8a6040518a63ffffffff1660e01b8152600401611e5d999897969594939291906154ca565b60006040518083038186803b158015611e7557600080fd5b505af4158015611e89573d6000803e3d6000fd5b5050505060005b8a811015611fd4576060611f268d8d84818110611ebd57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611ed2919061438a565b8a8a85818110611ef257634e487b7160e01b600052603260045260246000fd5b905060200201358d8d86818110611f1957634e487b7160e01b600052603260045260246000fd5b905060200201358461362e565b8a8a83818110611f4657634e487b7160e01b600052603260045260246000fd5b9050602002013561010060018b8b86818110611f7257634e487b7160e01b600052603260045260246000fd5b90506020020135611f8391906157ac565b81548110611fa157634e487b7160e01b600052603260045260246000fd5b906000526020600020016000828254611fba9190615755565b90915550829150611fcc905081615b1f565b915050611e90565b506000805b89811015612027578a8a8281811061200157634e487b7160e01b600052603260045260246000fd5b90506020020135826120139190615755565b91508061201f81615b1f565b915050611fd9565b50600183015463ffffffff600160e01b82048116600160c01b90920416101561209a578060fc6000336001600160a01b03166001600160a01b0316815260200190815260200160002060008f60000135815260200190815260200160002060008282546120949190615755565b90915550505b600183015463ffffffff600160e01b909104811610156120da578c35600090815260fd6020526040812080548392906120d4908490615755565b90915550505b6040516329ba982960e21b815260048101849052610101602482015260fe604482015260ff60648201526001600160a01b038716608482015260a48101829052733eb3e24cae6f1c587e8448fb64b87db4223d96e19063a6ea60a49060c40160006040518083038186803b15801561215157600080fd5b505af4158015612165573d6000803e3d6000fd5b5050505050505050505050505050505050565b61218061338b565b6101095460ff16156121a55760405163249fab5d60e01b815260040160405180910390fd5b8051610f8690610101906020840190613f7b565b733eb3e24cae6f1c587e8448fb64b87db4223d96e16360f0e59661010160fe60ff6121ec6097546001600160a01b031690565b866040518663ffffffff1660e01b815260040161220d95949392919061545c565b60006040518083038186803b15801561222557600080fd5b505af41580156115cc573d6000803e3d6000fd5b61224161338b565b610106805463ffffffff191663ffffffff92909216919091179055565b61226661338b565b6122706000613744565b565b6101018054819061228290615abe565b80601f01602080910402602001604051908101604052809291908181526020018280546122ae90615abe565b80156122fb5780601f106122d0576101008083540402835291602001916122fb565b820191906000526020600020905b8154815290600101906020018083116122de57829003601f168201915b505050600184015460028501546003860154600587015460408051808201825260068a01805461ffff908116835260078c01805485516020828102820181019097528181529c9d6001600160a01b039a8b169d998b169c5097909916995063ffffffff861698600160201b8704831698600160301b8804841698600160401b90980490931696958086019392919060009084015b828210156123d2576000848152602090819020604080518082019091529084015461ffff808216835262010000909104168183015282526001909201910161238f565b5050505081525050905089565b6123e761338b565b61010954600160301b900460ff16156124135760405163249fab5d60e01b815260040160405180910390fd5b610109805465ff000000000019169055565b61242d61338b565b60405160200161243c9061504c565b60405160208183030381529060405280519060200120816040516020016124639190614fb0565b604051602081830303815290604052805190602001201461249757604051635ee88f9760e01b815260040160405180910390fd5b50610109805461ff001916610100179055565b8635600090815260fb6020526040902060028101546001600160201b90910463ffffffff1611156124f45760028101546124f190600160201b900463ffffffff168861578d565b96505b604080516080810182526000808252602082015260609181018290528181019190915260028201546060908190600160401b900460ff16156126f4576000733eb3e24cae6f1c587e8448fb64b87db4223d96e1635ec01e4d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561257657600080fd5b505af415801561258a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ae9190614ced565b9050733eb3e24cae6f1c587e8448fb64b87db4223d96e16310f11a15610100610101600401886003018f866040518663ffffffff1660e01b81526004016125f995949392919061513a565b60006040518083038186803b15801561261157600080fd5b505af4158015612625573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261264d919081019061461a565b925082516001600160401b0381111561267657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561269f578160200160208202803683370190505b50915060005b83518110156126ed5760018382815181106126d057634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806126e581615b1f565b9150506126a5565b5050612792565b6040805160018082528183019092529060208083019080368337019050509150878260008151811061273657634e487b7160e01b600052603260045260246000fd5b602090810291909101015260408051600180825281830190925290816020016020820280368337019050509050898160008151811061278557634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60405180608001604052806127af6097546001600160a01b031690565b6001600160a01b03168152602001886001600160a01b031681526020018281526020018381525092505050733eb3e24cae6f1c587e8448fb64b87db4223d96e1630e3deb14836101018c60fc60fd6101008b8b8a6040518a63ffffffff1660e01b8152600401612827999897969594939291906154ca565b60006040518083038186803b15801561283f57600080fd5b505af4158015612853573d6000803e3d6000fd5b5050505060005b8160600151518110156129835760606128cb898460600151848151811061289157634e487b7160e01b600052603260045260246000fd5b6020026020010151856040015185815181106128bd57634e487b7160e01b600052603260045260246000fd5b60200260200101518461362e565b826040015182815181106128ef57634e487b7160e01b600052603260045260246000fd5b602002602001015161010060018560600151858151811061292057634e487b7160e01b600052603260045260246000fd5b602002602001015161293291906157ac565b8154811061295057634e487b7160e01b600052603260045260246000fd5b9060005260206000200160008282546129699190615755565b9091555082915061297b905081615b1f565b91505061285a565b50600182015463ffffffff600160e01b82048116600160c01b9092041610156129d75733600090815260fc602090815260408083208c358452909152812080548a92906129d1908490615755565b90915550505b600182015463ffffffff600160e01b90910481161015612a17578835600090815260fd6020526040812080548a9290612a11908490615755565b90915550505b6040516329ba982960e21b815260048101839052610101602482015260fe604482015260ff60648201526001600160a01b038616608482015260a48101899052733eb3e24cae6f1c587e8448fb64b87db4223d96e19063a6ea60a49060c40160006040518083038186803b158015612a8e57600080fd5b505af4158015612aa2573d6000803e3d6000fd5b50505050505050505050505050565b61010b8054610dac90615abe565b612ac761338b565b604051602001612ad69061504c565b6040516020818303038152906040528051906020012081604051602001612afd9190614fb0565b6040516020818303038152906040528051906020012014612b3157604051635ee88f9760e01b815260040160405180910390fd5b50610109805467ff000000000000001916600160381b179055565b8161010954600160281b900460ff1615612b6957612b6981613449565b612b738383613796565b505050565b612b8061338b565b61010954600160301b900460ff1615612bac5760405163249fab5d60e01b815260040160405180910390fd5b612bb46137a1565b610109805465ff00000000001916600160281b179055565b612bd461338b565b604051602001612be39061504c565b6040516020818303038152906040528051906020012081604051602001612c0a9190614fb0565b6040516020818303038152906040528051906020012014612c3e57604051635ee88f9760e01b815260040160405180910390fd5b61010954610100900460ff1615612c685760405163249fab5d60e01b815260040160405180910390fd5b60005b61010054811015612d02576101008181548110612c9857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154838281518110612cc357634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161015612cf057604051638a164f6360e01b815260040160405180910390fd5b80612cfa81615b1f565b915050612c6b565b50610100545b8251811015612d5657610100805460018101825560009182527f45e010b9ae401e2eb71529478da8bd513a9bdc2d095a111e324f5b95c09ed87b015580612d4e81615b1f565b915050612d08565b508151612b7390610105906020850190614039565b612d7361338b565b604051602001612d829061504c565b6040516020818303038152906040528051906020012081604051602001612da99190614fb0565b6040516020818303038152906040528051906020012014612ddd57604051635ee88f9760e01b815260040160405180910390fd5b50610109805463ff00000019166301000000179055565b612dfc61338b565b604051602001612e0b9061504c565b6040516020818303038152906040528051906020012081604051602001612e329190614fb0565b6040516020818303038152906040528051906020012014612e6657604051635ee88f9760e01b815260040160405180910390fd5b50610109805462ff0000191662010000179055565b6060610101600401805480602002602001604051908101604052809291908181526020018280548015612ef957602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612ebc5790505b5050505050905090565b337386b82972282dd22348374bc63fd21620f7ed847b14612f375760405163016bdfed60e71b815260040160405180910390fd5b61010480546001600160a01b0319166001600160a01b0392909216919091179055565b612f6261338b565b604051602001612f719061504c565b6040516020818303038152906040528051906020012081604051602001612f989190614fb0565b6040516020818303038152906040528051906020012014612fcc57604051635ee88f9760e01b815260040160405180910390fd5b50610109805460ff19166001179055565b612fe561338b565b61010954600160201b900460ff16156130115760405163249fab5d60e01b815260040160405180910390fd5b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b61303c61338b565b60405160200161304b9061504c565b60405160208183030381529060405280519060200120816040516020016130729190614fb0565b60405160208183030381529060405280519060200120146130a657604051635ee88f9760e01b815260040160405180910390fd5b50610109805466ff0000000000001916600160301b179055565b846001600160a01b03811633146130ed5761010954600160281b900460ff16156130ed576130ed33613449565b610ffb86868686866137c0565b61310261338b565b6001600160a01b0381166131675760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d4d565b6116cb81613744565b61317861338b565b610109546301000000900460ff16156131a45760405163249fab5d60e01b815260040160405180910390fd5b6113886131b46020830183614cd1565b61ffff1611156131d7576040516306b7c75960e31b815260040160405180910390fd5b60015b6131e76020830183615622565b9050811015613307576113886132006020840184615622565b8381811061321e57634e487b7160e01b600052603260045260246000fd5b90506040020160200160208101906132369190614cd1565b61ffff1611806132d7575061324e6020830183615622565b6132596001846157ac565b81811061327657634e487b7160e01b600052603260045260246000fd5b61328c9260206040909202019081019150614cd1565b61ffff1661329d6020840184615622565b838181106132bb57634e487b7160e01b600052603260045260246000fd5b6132d19260206040909202019081019150614cd1565b61ffff16115b156132f5576040516306b7c75960e31b815260040160405180910390fd5b806132ff81615b1f565b9150506131da565b5080610107612b738282615d9e565b60006001600160e01b03198216636cdb3d1360e11b148061334757506001600160e01b031982166303a24d0760e21b145b80610d9857506301ffc9a760e01b6001600160e01b0319831614610d98565b60006001600160e01b0319821663152a902d60e11b1480610d985750610d9882613316565b6097546001600160a01b031633146122705760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d4d565b60008082118015610d9857505061010054101590565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061343257613437565b613415565b50819003601f19909101908152919050565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa613485573d6000803e3d6000fd5b6000603a5250565b6001600160a01b0385163314806134a957506134a98533610c18565b6134c55760405162461bcd60e51b8152600401610d4d90615334565b6115cc8585858585613805565b600054610100900460ff166134f95760405162461bcd60e51b8152600401610d4d90615411565b6116cb816139f9565b600054610100900460ff166135295760405162461bcd60e51b8152600401610d4d90615411565b612270613a29565b6127106001600160601b038216111561359f5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610d4d565b6001600160a01b0382166135f55760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610d4d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760c955565b6001600160a01b03841661368e5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610d4d565b33600061369a85613a59565b905060006136a785613a59565b905060008681526065602090815260408083206001600160a01b038b168452909152812080548792906136db908490615755565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461373b83600089898989613ab2565b50505050505050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b610f86338383613c1d565b612270733cc6cdda760b79bafa08df41ecfa224f810dceb66001613cfe565b6001600160a01b0385163314806137dc57506137dc8533610c18565b6137f85760405162461bcd60e51b8152600401610d4d90615334565b6115cc8585858585613d74565b81518351146138675760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610d4d565b6001600160a01b03841661388d5760405162461bcd60e51b8152600401610d4d90615382565b3360005b84518110156139935760008582815181106138bc57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008583815181106138e857634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526065835260408082206001600160a01b038e1683529093529190912054909150818110156139395760405162461bcd60e51b8152600401610d4d906153c7565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290613978908490615755565b925050819055505050508061398c90615b1f565b9050613891565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516139e3929190615115565b60405180910390a4610ffb818787878787613ea2565b600054610100900460ff16613a205760405162461bcd60e51b8152600401610d4d90615411565b6116cb81613f6c565b600054610100900460ff16613a505760405162461bcd60e51b8152600401610d4d90615411565b61227033613744565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613aa157634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b15610ffb5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613af690899089908890889088906004016150bd565b602060405180830381600087803b158015613b1057600080fd5b505af1925050508015613b40575060408051601f3d908101601f19168201909252613b3d918101906148ee565b60015b613bed57613b4c615b8d565b806308c379a01415613b865750613b61615ba5565b80613b6c5750613b88565b8060405162461bcd60e51b8152600401610d4d9190615200565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610d4d565b6001600160e01b0319811663f23a6e6160e01b1461373b5760405162461bcd60e51b8152600401610d4d906152ec565b816001600160a01b0316836001600160a01b03161415613c915760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610d4d565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0390911690637d3e3dbe81613d2b5782613d245750634420e486613d2b565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af1613d6a578060005160e01c1415613d6a57600080fd5b5060006024525050565b6001600160a01b038416613d9a5760405162461bcd60e51b8152600401610d4d90615382565b336000613da685613a59565b90506000613db385613a59565b905060008681526065602090815260408083206001600160a01b038c16845290915290205485811015613df85760405162461bcd60e51b8152600401610d4d906153c7565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290613e37908490615755565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613e97848a8a8a8a8a613ab2565b505050505050505050565b6001600160a01b0384163b15610ffb5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613ee6908990899088908890889060040161505f565b602060405180830381600087803b158015613f0057600080fd5b505af1925050508015613f30575060408051601f3d908101601f19168201909252613f2d918101906148ee565b60015b613f3c57613b4c615b8d565b6001600160e01b0319811663bc197c8160e01b1461373b5760405162461bcd60e51b8152600401610d4d906152ec565b8051610f869060679060208401905b828054613f8790615abe565b90600052602060002090601f016020900481019282613fa95760008555613fef565b82601f10613fc257805160ff1916838001178555613fef565b82800160010185558215613fef579182015b82811115613fef578251825591602001919060010190613fd4565b50613ffb9291506140df565b5090565b828054828255906000526020600020908101928215613fef5791602002820182811115613fef578251825591602001919060010190613fd4565b82805482825590600052602060002090600701600890048101928215613fef5791602002820160005b838211156140a657835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302614062565b80156140d65782816101000a81549063ffffffff02191690556004016020816003010492830192600103026140a6565b5050613ffb9291505b5b80821115613ffb57600081556001016140e0565b80356140ff81615ec2565b919050565b60008083601f840112614115578182fd5b5081356001600160401b0381111561412b578182fd5b6020830191508360208260051b850101111561111057600080fd5b600082601f830112614156578081fd5b8135602061416382615732565b6040516141708282615af3565b8381528281019150858301600585901b8701840188101561418f578586fd5b855b858110156141b65781356141a481615ec2565b84529284019290840190600101614191565b5090979650505050505050565b600082601f8301126141d3578081fd5b813560206141e082615732565b6040516141ed8282615af3565b8381528281019150858301600585901b8701840188101561420c578586fd5b855b858110156141b65781358452928401929084019060010161420e565b600082601f83011261423a578081fd5b8135602061424782615732565b6040516142548282615af3565b8381528281019150858301600585901b87018401881015614273578586fd5b855b858110156141b657813561428881615efd565b84529284019290840190600101614275565b803580151581146140ff57600080fd5b60008083601f8401126142bb578182fd5b5081356001600160401b038111156142d1578182fd5b60208301915083602082850101111561111057600080fd5b600082601f8301126142f9578081fd5b81356001600160401b0381111561431257614312615b50565b604051614329601f8301601f191660200182615af3565b81815284602083860101111561433d578283fd5b816020850160208301379081016020019190915292915050565b600060408284031215610fe6578081fd5b80356001600160801b03811681146140ff57600080fd5b80356140ff81615efd565b60006020828403121561439b578081fd5b81356143a681615ec2565b9392505050565b600080604083850312156143bf578081fd5b82356143ca81615ec2565b915060208301356143da81615ec2565b809150509250929050565b600080600080600060a086880312156143fc578081fd5b853561440781615ec2565b9450602086013561441781615ec2565b935060408601356001600160401b0380821115614432578283fd5b61443e89838a016141c3565b94506060880135915080821115614453578283fd5b61445f89838a016141c3565b93506080880135915080821115614474578283fd5b50614481888289016142e9565b9150509295509295909350565b600080600080600060a086880312156144a5578283fd5b85356144b081615ec2565b945060208601356144c081615ec2565b9350604086013592506060860135915060808601356001600160401b038111156144e8578182fd5b614481888289016142e9565b60008060408385031215614506578182fd5b823561451181615ec2565b915061451f6020840161429a565b90509250929050565b6000806040838503121561453a578182fd5b823561454581615ec2565b946020939093013593505050565b60008060408385031215614565578182fd5b823561457081615ec2565b915060208301356143da81615eed565b600060208284031215614591578081fd5b81356001600160401b038111156145a6578182fd5b6145b284828501614146565b949350505050565b600080604083850312156145cc578182fd5b82356001600160401b03808211156145e2578384fd5b6145ee86838701614146565b93506020850135915080821115614603578283fd5b50614610858286016141c3565b9150509250929050565b6000602080838503121561462c578182fd5b82516001600160401b03811115614641578283fd5b8301601f81018513614651578283fd5b805161465c81615732565b6040516146698282615af3565b8281528481019150838501600584901b85018601891015614688578687fd5b8694505b838510156146aa57805183526001949094019391850191850161468c565b50979650505050505050565b600080604083850312156146c8578182fd5b82356001600160401b03808211156146de578384fd5b6146ea8683870161422a565b935060208501359150808211156146ff578283fd5b50614610858286016142e9565b60006020828403121561471d578081fd5b6143a68261429a565b600060208284031215614737578081fd5b5035919050565b600080600060608486031215614752578081fd5b833592506020840135915060408401356001600160401b0380821115614776578283fd5b90850190610180828803121561478a578283fd5b614792615709565b61479b83614368565b81526147a960208401614368565b60208201526147ba60408401614368565b60408201526147cb6060840161437f565b60608201526147dc6080840161437f565b60808201526147ed60a0840161437f565b60a08201526147fe60c0840161437f565b60c082015261480f60e0840161437f565b60e082015261010061482281850161437f565b9082015261012061483484820161429a565b90820152610140838101358381111561484b578586fd5b6148578a82870161422a565b828401525050610160915061486d8284016140f4565b828201528093505050509250925092565b600080600060608486031215614892578081fd5b833592506020840135915060408401356001600160401b038111156148b5578182fd5b840161012081870312156148c7578182fd5b809150509250925092565b6000602082840312156148e3578081fd5b81356143a681615ed7565b6000602082840312156148ff578081fd5b81516143a681615ed7565b60006020828403121561491b578081fd5b81356001600160401b03811115614930578182fd5b6145b2848285016142e9565b60008060008060808587031215614951578182fd5b84356001600160401b0380821115614967578384fd5b614973888389016142e9565b95506020870135915080821115614988578384fd5b614994888389016142e9565b945060408701359150808211156149a9578384fd5b50850161014081880312156149bc578283fd5b915060608501356149cc81615ec2565b939692955090935050565b60008060008060008060008060008060c08b8d0312156149f5578788fd5b8a356001600160401b0380821115614a0b57898afd5b614a178e838f01614357565b9b5060208d0135915080821115614a2c57898afd5b614a388e838f01614104565b909b50995060408d0135915080821115614a50578687fd5b614a5c8e838f01614104565b909950975060608d0135915080821115614a74578687fd5b614a808e838f01614104565b9097509550859150614a9460808e016140f4565b945060a08d0135915080821115614aa9578384fd5b50614ab68d828e016142aa565b915080935050809150509295989b9194979a5092959850565b600080600080600060808688031215614ae6578283fd5b85356001600160401b0380821115614afc578485fd5b614b0889838a01614357565b96506020880135955060408801359150614b2182615ec2565b90935060608701359080821115614b36578283fd5b50614b43888289016142aa565b969995985093965092949392505050565b600080600080600080600060c0888a031215614b6e578081fd5b87356001600160401b0380821115614b84578283fd5b614b908b838c01614357565b985060208a0135975060408a01359150614ba982615ec2565b90955060608901359450608089013590614bc282615ec2565b90935060a08901359080821115614bd7578283fd5b50614be48a828b016142aa565b989b979a50959850939692959293505050565b60008060008060008060a08789031215614c0f578384fd5b86356001600160401b0380821115614c25578586fd5b614c318a838b01614357565b9750602089013596506040890135955060608901359150614c5182615ec2565b90935060808801359080821115614c66578384fd5b50614c7389828a016142aa565b979a9699509497509295939492505050565b600060208284031215614c96578081fd5b81356001600160401b03811115614cab578182fd5b6145b284828501614357565b600060208284031215614cc8578081fd5b6143a682614368565b600060208284031215614ce2578081fd5b81356143a681615eed565b600060208284031215614cfe578081fd5b5051919050565b60008060408385031215614d17578182fd5b50508035926020909101359150565b600060208284031215614d37578081fd5b81356143a681615efd565b6000815180845260208085019450808401835b83811015614d7157815187529582019590820190600101614d55565b509495945050505050565b805480835260008281526020808220940193909190825b82600782011015614e0b57815463ffffffff8082168852602082811c821690890152604082811c821690890152606082811c821690890152608082811c82169089015260a082811c82169089015260c082811c9091169088015260e090811c9087015261010090950194600190910190600801614d93565b90549082811015614e295763ffffffff821686526020909501946001015b82811015614e4957602082901c63ffffffff168652602095909501946001015b82811015614e685763ffffffff604083901c1686526020909501946001015b82811015614e875763ffffffff606083901c1686526020909501946001015b82811015614ea65763ffffffff608083901c1686526020909501946001015b82811015614ec55763ffffffff60a083901c1686526020909501946001015b82811015614ee45763ffffffff60c083901c1686526020909501946001015b82811015614efa5760e082901c86526020860195505b5093949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614f458160208601602086016159ae565b601f01601f19169290920160200192915050565b600060018060a01b0380835116845280602084015116602085015250604082015160806040850152614f8e6080850182614d42565b905060608301518482036060860152614fa78282614d42565b95945050505050565b60008251614fc28184602087016159ae565b9190910192915050565b6000808454614fda81615abe565b60018281168015614ff257600181146150035761502f565b60ff1984168752828701945061502f565b8886526020808720875b858110156150265781548a82015290840190820161500d565b50505082870194505b5050505083516150438183602088016159ae565b01949350505050565b663337b932bb32b960c91b815260070190565b6001600160a01b0386811682528516602082015260a06040820181905260009061508b90830186614d42565b828103606084015261509d8186614d42565b905082810360808401526150b18185614f2d565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906150f790830184614f2d565b979650505050505050565b6020815260006143a66020830184614d42565b6040815260006151286040830185614d42565b8281036020840152614fa78185614d42565b600060a0820160a0835280885480835260c08501915089845260209250828420845b828110156151785781548452928401926001918201910161515c565b5050508381038285015261518c8189614d7c565b91505082810360408401526151a18187614d7c565b60608401959095525050608001529392505050565b6020808252825182820181905260009190848201906040850190845b818110156151f457835163ffffffff16835292840192918401916001016151d2565b50909695505050505050565b6020815260006143a66020830184614f2d565b60006101208083526152278184018d614f2d565b9050602060018060a01b03808d16828601526040818d1681870152818c16606087015263ffffffff8b16608087015261ffff9150818a1660a087015281891660c087015281881660e087015285840361010087015280840182885116855283880151828587015281815180845260608801915086830197508893505b808410156152d35787518051871683528781015187168884015297870197600194909401939250908401906152a3565b50809750505050505050509a9950505050505050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060a082018783526020878185015286604085015260018060a01b03808716606086015260a0608086015282865180855260c0870191508388019450855b818110156154b957855184168352948401949184019160010161549b565b50909b9a5050505050505050505050565b60006101008b83528a6020840152806040840152893581840152506020890135601e198a36030181126154fb578182fd5b890180356001600160401b03811115615512578283fd5b8060051b8036038c1315615524578384fd5b604061012086015261014085018290526101606001600160fb1b0383111561554a578485fd5b816020850182880137818601935080840192508483528b60608701528a60808701528960a0870152808685030160c08701525050615589818789614f04565b91505082810360e084015261559e8185614f59565b9c9b505050505050505050505050565b6001600160801b038c811682528b811660208301528a16604082015263ffffffff8981166060830152888116608083015287811660a083015286811660c083015285811660e083015284166101008201528215156101208201526001600160a01b038216610140820152610160810161559e565b6000808335601e19843603018112615638578283fd5b8301803591506001600160401b03821115615651578283fd5b6020019150600681901b360382131561111057600080fd5b6000808335601e1984360301811261567f578283fd5b8301803591506001600160401b03821115615698578283fd5b6020019150600581901b360382131561111057600080fd5b6000808335601e198436030181126156c6578283fd5b8301803591506001600160401b038211156156df578283fd5b60200191503681900382131561111057600080fd5b60008235603e19833603018112614fc2578182fd5b60405161018081016001600160401b038111828210171561572c5761572c615b50565b60405290565b60006001600160401b0382111561574b5761574b615b50565b5060051b60200190565b6000821982111561576857615768615b3a565b500190565b60008261578857634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156157a7576157a7615b3a565b500290565b6000828210156157be576157be615b3a565b500390565b5b81811015610f8657600081556001016157c4565b600160401b8311156157ec576157ec615b50565b805483825580841015615845578160005260206000206007850160031c8101601c8660021b16801561582f576000198083018054828460200360031b1c16815550505b506158426007840160031c8301826157c3565b50505b506000818152602081208391805b8681101561373b5761588761586785615b80565b845463ffffffff600386901b81811b801990931693909116901b16178455565b602084019350600482019150601c8211156158a757600091506001830192505b600101615853565b6001600160401b038311156158c6576158c6615b50565b6158d08154615abe565b600080601f8611601f8411818117156158ef5760008681526020902092505b801561591e57601f880160051c8301602089101561590a5750825b61591c601f870160051c8501826157c3565b505b50806001811461595257600094508715615939578387013594505b600188901b60001960038a901b1c1986161786556159a4565b601f198816945082845b8681101561597c578886013582556020958601956001909201910161595c565b50888610156159995760001960f88a60031b161c19858901351681555b5060018860011b0186555b5050505050505050565b60005b838110156159c95781810151838201526020016159b1565b838111156159d8576000848401525b50505050565b81356159e981615eed565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615a1557600080fd5b840180356001600160401b03811115615a2d57600080fd5b6020820191508060061b3603821315615a4557600080fd5b600160401b811115615a5957615a59615b50565b825481845580821015615a8e576000848152602081208381019083015b80821015615a8a5782825590870190615a76565b5050505b50600092835260208320925b8181101561373b57615aac8385615e7e565b92840192604092909201918401615a9a565b600181811c90821680615ad257607f821691505b60208210811415610fe657634e487b7160e01b600052602260045260246000fd5b601f8201601f191681016001600160401b0381118282101715615b1857615b18615b50565b6040525050565b6000600019821415615b3357615b33615b3a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610d9881615ec2565b60008135610d9881615eed565b60008135610d9881615efd565b600060033d1115615ba257600481823e5160e01c5b90565b600060443d1015615bb35790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615be257505050505090565b8285019150815181811115615bfa5750505050505090565b843d8701016020828501011115615c145750505050505090565b615c2360208286010187615af3565b509095945050505050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b615c5882836156b0565b615c638183856158af565b5050615c7d615c7460208401615b66565b60018301615c2e565b615c95615c8c60408401615b66565b60028301615c2e565b615cad615ca460608401615b66565b60038301615c2e565b615cba6080830183615669565b615cc88183600486016157d8565b505060058101615cf4615cdd60a08501615b80565b825463ffffffff191663ffffffff91909116178255565b615d21615d0360c08501615b73565b825465ffff00000000191660209190911b65ffff0000000016178255565b615d52615d3060e08501615b73565b825467ffff000000000000191660309190911b67ffff00000000000016178255565b615d83615d626101008501615b73565b825461ffff60401b191660409190911b69ffff000000000000000016178255565b50610f86615d956101208401846156f4565b600683016159de565b8135615da981615eed565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615dd557600080fd5b840180356001600160401b03811115615ded57600080fd5b6020820191508060061b3603821315615e0557600080fd5b600160401b811115615e1957615e19615b50565b825481845580821015615e4e576000848152602081208381019083015b80821015615e4a5782825590870190615e36565b5050505b50600092835260208320925b8181101561373b57615e6c8385615e7e565b92840192604092909201918401615e5a565b8135615e8981615eed565b815461ffff191661ffff8216178255506020820135615ea781615eed565b815463ffff0000191660109190911b63ffff00001617905550565b6001600160a01b03811681146116cb57600080fd5b6001600160e01b0319811681146116cb57600080fd5b61ffff811681146116cb57600080fd5b63ffffffff811681146116cb57600080fdfea2646970667358221220dc567c006e00992ae4728b07f5875afa89a591ed397cf74afade23a7ff3e0cd364736f6c63430008040033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.