Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Archetype
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Archetype v0.6.0 - ERC1155-Random // // 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 "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.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 "@openzeppelin/contracts-upgradeable/token/common/ERC2981Upgradeable.sol"; import "solady/src/utils/LibString.sol"; import "closedsea/src/OperatorFilterer.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 public totalSupply; Config public config; BurnConfig public burnConfig; Options public options; string public name; string public symbol; // chainlink VrfConfig public vrfConfig; mapping(uint256 => VrfMintInfo) public requestIdMintInfo; VRFCoordinatorV2Interface internal vrfCoordinator; // // METHODS // function initialize( string memory _name, string memory _symbol, Config calldata config_, address _receiver ) external initializer { name = _name; symbol = _symbol; __ERC1155_init(""); vrfCoordinator = VRFCoordinatorV2Interface(VRF_CORDINATOR); // 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_; __Ownable_init(); if (config.ownerAltPayout != address(0)) { setDefaultRoyalty(config.ownerAltPayout, config.defaultRoyalty); } else { setDefaultRoyalty(_receiver, config.defaultRoyalty); } } // // PUBLIC // function mint( Auth calldata auth, uint256 quantity, address affiliate, bytes calldata signature ) external payable { mintTo(auth, quantity, _msgSender(), affiliate, signature); } function mintTo( Auth calldata auth, uint256 quantity, address to, address affiliate, bytes calldata signature ) public payable { DutchInvite storage i = invites[auth.key]; if (i.unitSize > 1) { quantity = quantity * i.unitSize; } ValidationArgs memory args = ValidationArgs({ owner: owner(), affiliate: affiliate, quantity: quantity, curSupply: totalSupply }); ArchetypeLogic.validateMint( i, config, auth, _minted, _listSupply, signature, args ); if(vrfConfig.enabled) { uint256 requestId = requestRandomness(); // request randomness from Chainlink VRF requestIdMintInfo[requestId] = VrfMintInfo({ key: auth.key, to: to, quantity: quantity }); } else { uint16[] memory tokenIds; uint256 seed = ArchetypeLogic.random(); tokenIds = ArchetypeLogic.getRandomTokenIds( config.tokenPool, i.tokenIdsExcluded, quantity, seed ); for (uint256 j = 0; j < tokenIds.length; j++) { bytes memory _data; _mint(to, tokenIds[j], 1, _data); } } totalSupply += quantity; if (i.limit < i.maxSupply) { _minted[_msgSender()][auth.key] += quantity; } if (i.maxSupply < 2**32 - 1) { _listSupply[auth.key] += quantity; } ArchetypeLogic.updateBalances(i, config, _ownerBalance, _affiliateBalance, affiliate, quantity); } // simple 1 to 1 burn to mint. function burnToMint(uint256[] calldata tokenIdList, uint256[] calldata quantityList) external { if(burnConfig.tokenAddress == address(0)) { revert BurnToMintDisabled(); } if (quantityList.length != tokenIdList.length) { revert InvalidConfig(); } address msgSender = _msgSender(); uint256 quantity = 0; for (uint256 i; i < tokenIdList.length; i++) { address burnAddress = burnConfig.burnAddress != address(0) ? burnConfig.burnAddress : address(0x000000000000000000000000000000000000dEaD); bytes memory _data; IERC1155Upgradeable(burnConfig.tokenAddress).safeTransferFrom(msgSender, burnAddress, tokenIdList[i], quantityList[i], _data); _mint(msgSender, tokenIdList[i], quantityList[i], _data); quantity += quantityList[i]; } if ((totalSupply + quantity) > config.maxSupply) { revert MaxSupplyExceeded(); } totalSupply += quantity; } function uri(uint256 tokenId) public view override returns (string memory) { 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 tokenPool() external view returns (uint16[] memory) { return config.tokenPool; } function computePrice( bytes32 key, uint256 quantity, bool affiliateUsed ) external view returns (uint256) { DutchInvite storage i = invites[key]; return ArchetypeLogic.computePrice(i, config.discounts, quantity, affiliateUsed); } // // OWNER ONLY // function airdropTo( address[] calldata toList, uint256[] calldata quantityList, uint256[] calldata tokenIdList ) external _onlyOwner { if (options.airdropLocked) { revert LockedForever(); } if (quantityList.length != toList.length || quantityList.length != tokenIdList.length) { revert InvalidConfig(); } uint256 quantity = 0; for (uint256 i = 0; i < toList.length; i++) { bytes memory _data; _mint(toList[i], tokenIdList[i], quantityList[i], _data); quantity += quantityList[i]; } if ((totalSupply + quantity) > config.maxSupply) { revert MaxSupplyExceeded(); } totalSupply += quantity; } /// @notice the password is "forever" function lockAirdrop(string memory password) external _onlyOwner { _checkPassword(password); options.airdropLocked = true; } 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 { _checkPassword(password); options.uriLocked = true; } /// @notice the password is "forever" // token pool will be appended. Be careful changing. function appendTokenPool(uint16[] memory newTokens, string memory password) public _onlyOwner { _checkPassword(password); if (options.tokenPoolLocked) { revert LockedForever(); } for (uint256 i = 0; i < newTokens.length; i++) { config.tokenPool.push(newTokens[i]); } } /// @notice the password is "forever" // token pool will be completely replaced. Be careful changing. function replaceTokenPool(uint16[] memory newTokens, string memory password) external _onlyOwner { _checkPassword(password); if (options.tokenPoolLocked) { revert LockedForever(); } config.tokenPool = newTokens; } /// @notice the password is "forever" function lockTokenPool(string memory password) external _onlyOwner { _checkPassword(password); options.tokenPoolLocked = true; } /// @notice the password is "forever" // max supply cannot subceed total supply. Be careful changing. function setMaxSupply(uint32 maxSupply, string memory password) external _onlyOwner { _checkPassword(password); if (options.maxSupplyLocked) { revert LockedForever(); } if (maxSupply < totalSupply) { revert MaxSupplyExceeded(); } config.maxSupply = maxSupply; } /// @notice the password is "forever" function lockMaxSupply(string memory password) external _onlyOwner { _checkPassword(password); 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 { _checkPassword(password); 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 { _checkPassword(password); options.discountsLocked = 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 { _checkPassword(password); options.ownerAltPayoutLocked = true; } function setMaxBatchSize(uint16 maxBatchSize) external _onlyOwner { config.maxBatchSize = maxBatchSize; } function enableChainlinkVRF(uint64 subId) external _onlyOwner { vrfConfig = VrfConfig({ enabled: true, subId: subId }); } function disableChainlinkVRF() external _onlyOwner { vrfConfig = VrfConfig({ enabled: false, subId: 0 }); } 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, tokenAddress: _invite.tokenAddress, tokenIdsExcluded: _invite.tokenIdsExcluded }); 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); } function enableBurnToMint( address tokenAddress, address burnAddress ) external _onlyOwner { burnConfig = BurnConfig({ tokenAddress: tokenAddress, burnAddress: burnAddress }); } function disableBurnToMint() external _onlyOwner { burnConfig = BurnConfig({ tokenAddress: address(0), burnAddress: address(0) }); } // // PLATFORM ONLY // function setSuperAffiliatePayout(address superAffiliatePayout) external _onlyPlatform { config.superAffiliatePayout = superAffiliatePayout; } // // VRF // // Request randomness function requestRandomness() internal returns (uint256 requestId) { // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2/supported-networks/#configurations bytes32 keyHash = VRF_KEYHASH; uint16 minimumRequestConfirmations = 5; uint32 callbackGasLimit = 2500000; // max limit // Requesting random numbers requestId = vrfCoordinator.requestRandomWords( keyHash, vrfConfig.subId, minimumRequestConfirmations, callbackGasLimit, 1 ); } // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF function rawFulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) external { // Allow owner and platform to fulfill as backup address msgSender = _msgSender(); if(msgSender == VRF_CORDINATOR || msgSender == PLATFORM || msgSender == owner()) { fulfillRandomWords(requestId, randomWords); } else { revert NotVRF(); } } function fulfillRandomWords(uint256 requestId, uint256[] memory randomness) internal { VrfMintInfo memory mintInfo = requestIdMintInfo[requestId]; if(mintInfo.quantity == 0) { revert InvalidRequestId(); } uint16[] memory tokenIds; tokenIds = ArchetypeLogic.getRandomTokenIds( config.tokenPool, invites[mintInfo.key].tokenIdsExcluded, mintInfo.quantity, randomness[0] ); for (uint256 j = 0; j < tokenIds.length; j++) { bytes memory _data; _mint(mintInfo.to, tokenIds[j], 1, _data); } delete requestIdMintInfo[requestId]; } // // INTERNAL // function _startTokenId() internal view virtual returns (uint256) { return 1; } function _msgSender() internal view override returns (address) { return msg.sender == BATCH? tx.origin: msg.sender; } function _checkPassword(string memory password) internal pure { if (keccak256(abi.encodePacked(password)) != keccak256(abi.encodePacked("forever"))) { revert WrongPassword(); } } function _isOwner() internal view { if (_msgSender() != owner()) { revert NotOwner(); } } modifier _onlyPlatform() { if (_msgSender() != PLATFORM) { revert NotPlatform(); } _; } modifier _onlyOwner() { _isOwner(); _; } //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 pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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.9.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.9.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] * ```solidity * 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 Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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.9.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.9.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.9.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.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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.6.0 - ERC1155-random // // 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 TokenPoolEmpty(); error NumberOfMintsExceeded(); error MintingPaused(); error InvalidReferral(); error InvalidSignature(); error BalanceEmpty(); error TransferFailed(); error MaxBatchSizeExceeded(); error BurnToMintDisabled(); error NotTokenOwner(); error NotPlatform(); error NotOwner(); error NotVRF(); error NotApprovedToTransfer(); error InvalidAmountOfTokens(); error WrongPassword(); error LockedForever(); error URIQueryForNonexistentToken(); error InvalidTokenId(); error MaxRetriesExceeded(); error InvalidRequestId(); // // 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; uint16 maxBatchSize; uint16 affiliateFee; //BPS uint16 platformFee; //BPS uint16 defaultRoyalty; //BPS Discount discounts; uint16[] tokenPool; // flattened list of all mintable tokens } struct Options { bool uriLocked; bool maxSupplyLocked; bool tokenPoolLocked; bool affiliateFeeLocked; bool discountsLocked; bool ownerAltPayoutLocked; bool provenanceHashLocked; bool airdropLocked; bool useChainlinkVRF; } struct DutchInvite { uint128 price; uint128 reservePrice; uint128 delta; uint32 start; uint32 end; uint32 limit; uint32 maxSupply; uint32 interval; uint32 unitSize; // mint 1 get x address tokenAddress; uint16[] tokenIdsExcluded; // token ids excluded from this list } struct Invite { uint128 price; uint32 start; uint32 end; uint32 limit; uint32 maxSupply; uint32 unitSize; // mint 1 get x address tokenAddress; uint16[] tokenIdsExcluded; // token ids excluded from this list } struct OwnerBalance { uint128 owner; uint128 platform; } struct ValidationArgs { address owner; address affiliate; uint256 quantity; uint256 curSupply; } struct BurnConfig { address tokenAddress; address burnAddress; } struct VrfConfig { bool enabled; uint64 subId; } struct VrfMintInfo { bytes32 key; address to; uint256 quantity; } address constant PLATFORM = 0x86B82972282Dd22348374bC63fd21620F7ED847B; address constant BATCH = 0x6Bc558A6DC48dEfa0e7022713c23D65Ab26e4Fa7; uint16 constant MAXBPS = 5000; // max fee or discount is 50% address constant VRF_CORDINATOR = 0x271682DEB8C4E0901D1a1550aD2e64D568E69909; bytes32 constant VRF_KEYHASH = 0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef; 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, bytes calldata signature, ValidationArgs memory args ) public view { address msgSender = _msgSender(); if (args.affiliate != address(0)) { if ( args.affiliate == PLATFORM || args.affiliate == args.owner || args.affiliate == msgSender ) { revert InvalidReferral(); } validateAffiliate(args.affiliate, signature, config.affiliateSigner); } if (i.limit == 0) { revert MintingPaused(); } if (!verify(auth, i.tokenAddress, msgSender)) { revert WalletUnauthorizedToMint(); } if (block.timestamp < i.start) { revert MintNotYetStarted(); } if (i.end > i.start && block.timestamp > i.end) { revert MintEnded(); } { uint256 totalAfterMint; if (i.limit < i.maxSupply) { totalAfterMint = minted[msgSender][auth.key] + args.quantity; if (totalAfterMint > i.limit) { revert NumberOfMintsExceeded(); } } if (i.maxSupply < config.maxSupply) { totalAfterMint = listSupply[auth.key] + args.quantity; if (totalAfterMint > i.maxSupply) { revert ListMaxSupplyExceeded(); } } } if (args.quantity > config.maxBatchSize) { revert MaxBatchSizeExceeded(); } if ((args.curSupply + args.quantity) > config.maxSupply) { revert MaxSupplyExceeded(); } if (args.quantity > config.tokenPool.length) { revert TokenPoolEmpty(); } uint256 cost = computePrice(i, config.discounts, args.quantity, args.affiliate != address(0)); if (i.tokenAddress != address(0)) { IERC20Upgradeable erc20Token = IERC20Upgradeable(i.tokenAddress); if (erc20Token.allowance(msgSender, address(this)) < cost) { revert NotApprovedToTransfer(); } if (erc20Token.balanceOf(msgSender) < 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(_msgSender(), 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 { address msgSender = _msgSender(); for (uint256 i = 0; i < tokens.length; i++) { address tokenAddress = tokens[i]; uint128 wad = 0; if (msgSender == owner || msgSender == config.ownerAltPayout || msgSender == PLATFORM) { OwnerBalance storage balance = _ownerBalance[tokenAddress]; if (msgSender == owner || msgSender == config.ownerAltPayout) { wad = balance.owner; balance.owner = 0; } else { wad = balance.platform; balance.platform = 0; } } else { wad = _affiliateBalance[msgSender][tokenAddress]; _affiliateBalance[msgSender][tokenAddress] = 0; } if (wad == 0) { revert BalanceEmpty(); } if (tokenAddress == address(0)) { bool success = false; // send to ownerAltPayout if set and owner is withdrawing if (msgSender == owner && config.ownerAltPayout != address(0)) { (success, ) = payable(config.ownerAltPayout).call{ value: wad }(""); } else { (success, ) = msgSender.call{ value: wad }(""); } if (!success) { revert TransferFailed(); } } else { IERC20Upgradeable erc20Token = IERC20Upgradeable(tokenAddress); if (msgSender == owner && config.ownerAltPayout != address(0)) { erc20Token.transfer(config.ownerAltPayout, wad); } else { erc20Token.transfer(msgSender, wad); } } emit Withdrawal(msgSender, 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( uint16[] storage tokenPool, uint16[] memory tokenIdsExcluded, uint256 quantity, uint256 seed ) public returns (uint16[] memory) { uint16[] memory tokenIds = new uint16[](quantity); uint256 retries = 0; uint256 MAX_RETRIES = 5; uint256 i = 0; while (i < quantity) { if (tokenPool.length == 0) { revert MaxSupplyExceeded(); } uint256 rand = uint256(keccak256(abi.encode(seed, i))); uint256 randIdx = rand % tokenPool.length; uint16 selectedToken = tokenPool[randIdx]; if (tokenIdsExcluded.length > 0 && isExcluded(selectedToken, tokenIdsExcluded)) { // If the token is excluded, retry for this position in tokenIds array seed = rand; // Update the seed for the next iteration retries++; if (retries >= MAX_RETRIES) { revert MaxRetriesExceeded(); } continue; } tokenIds[i] = selectedToken; // remove token from pool tokenPool[randIdx] = tokenPool[tokenPool.length - 1]; tokenPool.pop(); retries = 0; i++; } return tokenIds; } function isExcluded(uint16 tokenId, uint16[] memory excludedList) internal pure returns (bool) { for (uint256 i = 0; i < excludedList.length; i++) { if (tokenId == excludedList[i]) { return true; } } return false; } function random() public view returns (uint256) { uint256 randomHash = uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp))); return randomHash; } function _msgSender() internal view returns (address) { return msg.sender == BATCH ? tx.origin : msg.sender; } }
// 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": "0x365110b34b46927b2158e07e6d3c6d4802e032f0" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"BurnToMintDisabled","type":"error"},{"inputs":[],"name":"InvalidConfig","type":"error"},{"inputs":[],"name":"InvalidRequestId","type":"error"},{"inputs":[],"name":"LockedForever","type":"error"},{"inputs":[],"name":"MaxSupplyExceeded","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotPlatform","type":"error"},{"inputs":[],"name":"NotVRF","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":"toList","type":"address[]"},{"internalType":"uint256[]","name":"quantityList","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"}],"name":"airdropTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"newTokens","type":"uint16[]"},{"internalType":"string","name":"password","type":"string"}],"name":"appendTokenPool","outputs":[],"stateMutability":"nonpayable","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":[],"name":"burnConfig","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"burnAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"},{"internalType":"uint256[]","name":"quantityList","type":"uint256[]"}],"name":"burnToMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bool","name":"affiliateUsed","type":"bool"}],"name":"computePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"maxSupply","type":"uint32"},{"internalType":"uint16","name":"maxBatchSize","type":"uint16"},{"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":"disableBurnToMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableChainlinkVRF","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"burnAddress","type":"address"}],"name":"enableBurnToMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"}],"name":"enableChainlinkVRF","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":"uint16","name":"maxBatchSize","type":"uint16"},{"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":"uint16[]","name":"tokenPool","type":"uint16[]"}],"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":"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":"lockAirdrop","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":"lockTokenPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"password","type":"string"}],"name":"lockURI","outputs":[],"stateMutability":"nonpayable","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":"address","name":"affiliate","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mintTo","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":"tokenPoolLocked","type":"bool"},{"internalType":"bool","name":"affiliateFeeLocked","type":"bool"},{"internalType":"bool","name":"discountsLocked","type":"bool"},{"internalType":"bool","name":"ownerAltPayoutLocked","type":"bool"},{"internalType":"bool","name":"provenanceHashLocked","type":"bool"},{"internalType":"bool","name":"airdropLocked","type":"bool"},{"internalType":"bool","name":"useChainlinkVRF","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":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"newTokens","type":"uint16[]"},{"internalType":"string","name":"password","type":"string"}],"name":"replaceTokenPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestIdMintInfo","outputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"affiliateFee","type":"uint16"}],"name":"setAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseUri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint16","name":"feeNumerator","type":"uint16"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"affiliateDiscount","type":"uint16"},{"components":[{"internalType":"uint16","name":"numMints","type":"uint16"},{"internalType":"uint16","name":"mintDiscount","type":"uint16"}],"internalType":"struct MintTier[]","name":"mintTiers","type":"tuple[]"}],"internalType":"struct Discount","name":"discounts","type":"tuple"}],"name":"setDiscounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"},{"internalType":"bytes32","name":"_cid","type":"bytes32"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"},{"internalType":"uint128","name":"delta","type":"uint128"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"uint32","name":"limit","type":"uint32"},{"internalType":"uint32","name":"maxSupply","type":"uint32"},{"internalType":"uint32","name":"interval","type":"uint32"},{"internalType":"uint32","name":"unitSize","type":"uint32"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint16[]","name":"tokenIdsExcluded","type":"uint16[]"}],"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":"address","name":"tokenAddress","type":"address"},{"internalType":"uint16[]","name":"tokenIdsExcluded","type":"uint16[]"}],"internalType":"struct Invite","name":"_invite","type":"tuple"}],"name":"setInvite","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"maxBatchSize","type":"uint16"}],"name":"setMaxBatchSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"maxSupply","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":"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":[],"name":"tokenPool","outputs":[{"internalType":"uint16[]","name":"","type":"uint16[]"}],"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":"vrfConfig","outputs":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"uint64","name":"subId","type":"uint64"}],"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
608060405234801561001057600080fd5b50615f4380620000216000396000f3fe6080604052600436106103a15760003560e01c806379b004db116101e7578063b828aa831161010d578063e985e9c5116100a0578063f2fde38b1161006f578063f2fde38b14610e5a578063f7d1f2ca14610e7a578063fd614f2a14610e9a578063fec5176e14610eba57600080fd5b8063e985e9c514610db1578063ead0055314610dfa578063ed42802714610e1a578063f242432a14610e3a57600080fd5b8063ce216e2f116100dc578063ce216e2f14610d3c578063d25e2cd614610d5c578063d71d8d2314610d71578063de6cd0db14610d9157600080fd5b8063b828aa8314610c41578063bedcf00314610c8a578063c7494df714610cfc578063caf3e53214610d1c57600080fd5b8063978a450911610185578063a402628411610154578063a402628414610aaa578063a5aa4aa414610aca578063aa85448114610bd7578063b518e16a14610c2157600080fd5b8063978a4509146109d05780639a7a973c14610a1a578063a22cb46514610a47578063a3edb86a14610a6757600080fd5b806384a0b9eb116101c157806384a0b9eb1461096a5780638da5cb5b1461098a5780639564e8e4146109a857806395d89b41146109bb57600080fd5b806379b004db1461090a5780637c5d0a081461092a5780637d08782d1461094a57600080fd5b80632eb2c2d6116102cc578063493b2d211161026a57806355f804b31161023957806355f804b31461088a5780635ecb16cd146108aa578063715018a6146108ca57806379502c55146108df57600080fd5b8063493b2d21146107ef5780634a21a2df1461080f5780634bde38c8146108225780634e1273f41461085d57600080fd5b80633fb3b20a116102a65780633fb3b20a1461076f578063400e3db91461078f5780634331f639146107af57806347dd4636146107cf57600080fd5b80632eb2c2d61461071a57806332f7c6d41461073a5780633ccfd60b1461075a57600080fd5b806310566ef6116103445780631fe543e3116103135780631fe543e3146105bc57806321d5bf24146105dc57806327a59437146106435780632a55205a146106db57600080fd5b806310566ef6146104af5780631069143a146104c457806318160ddd1461058557806318e201121461059c57600080fd5b806306fdde031161038057806306fdde031461042b5780630c6f910b1461044d5780630e89341c1461046d578063104e99291461048d57600080fd5b8062fdd58e146103a657806301ffc9a7146103d957806303be0ce614610409575b600080fd5b3480156103b257600080fd5b506103c66103c136600461446f565b610f23565b6040519081526020015b60405180910390f35b3480156103e557600080fd5b506103f96103f4366004614925565b610fbb565b60405190151581526020016103d0565b34801561041557600080fd5b506104296104243660046142f4565b610fdb565b005b34801561043757600080fd5b5061044061102c565b6040516103d09190615210565b34801561045957600080fd5b50610429610468366004614b82565b6110bb565b34801561047957600080fd5b50610440610488366004614759565b611139565b34801561049957600080fd5b506104a261119b565b6040516103d09190614e65565b3480156104bb57600080fd5b5061042961121f565b3480156104d057600080fd5b5061010a546105339060ff80821691610100810482169162010000820481169163010000008104821691600160201b820481169165010000000000810482169166010000000000008204811691600160381b8104821691600160401b9091041689565b604080519915158a5297151560208a01529515159688019690965292151560608701529015156080860152151560a0850152151560c084015290151560e08301521515610100820152610120016103d0565b34801561059157600080fd5b506103c66101005481565b3480156105a857600080fd5b506104296105b736600461469b565b61125c565b3480156105c857600080fd5b506104296105d7366004614bb6565b611326565b3480156105e857600080fd5b5061062b6105f73660046142f4565b6001600160a01b03918216600090815260ff602090815260408083209390941682529190915220546001600160801b031690565b6040516001600160801b0390911681526020016103d0565b34801561064f57600080fd5b506106b461065e3660046142d1565b6040805180820190915260008082526020820152506001600160a01b0316600090815260fe60209081526040918290208251808401909352546001600160801b038082168452600160801b909104169082015290565b6040805182516001600160801b0390811682526020938401511692810192909252016103d0565b3480156106e757600080fd5b506106fb6106f6366004614bf0565b6113b9565b604080516001600160a01b0390931683526020830191909152016103d0565b34801561072657600080fd5b5061042961073536600461432c565b611467565b34801561074657600080fd5b5061042961075536600461495d565b6114c5565b34801561076657600080fd5b506104296114f1565b34801561077b57600080fd5b5061042961078a36600461495d565b611562565b34801561079b57600080fd5b506104296107aa366004614c2d565b61158e565b3480156107bb57600080fd5b506104296107ca36600461449a565b61161b565b3480156107db57600080fd5b506104296107ea36600461469b565b611654565b3480156107fb57600080fd5b5061042961080a3660046144c7565b6116a4565b61042961081d366004614ab1565b61184a565b34801561082e57600080fd5b507386b82972282dd22348374bc63fd21620f7ed847b5b6040516001600160a01b0390911681526020016103d0565b34801561086957600080fd5b5061087d610878366004614596565b61185f565b6040516103d091906151d8565b34801561089657600080fd5b506104296108a536600461495d565b6119c0565b3480156108b657600080fd5b506104296108c536600461455c565b611a01565b3480156108d657600080fd5b50610429611a81565b3480156108eb57600080fd5b506108f4611a95565b6040516103d09a99989796959493929190615223565b34801561091657600080fd5b50610429610925366004614b82565b611c0f565b34801561093657600080fd5b5061042961094536600461495d565b611c3a565b34801561095657600080fd5b506104296109653660046146f1565b611c5e565b34801561097657600080fd5b5061042961098536600461489d565b611e9b565b34801561099657600080fd5b506097546001600160a01b0316610845565b6104296109b6366004614a2a565b612154565b3480156109c757600080fd5b506104406125bd565b3480156109dc57600080fd5b5061062b6109eb3660046142d1565b6001600160a01b0316600090815260ff602090815260408083208380529091529020546001600160801b031690565b348015610a2657600080fd5b506103c6610a35366004614759565b600090815260fd602052604090205490565b348015610a5357600080fd5b50610429610a6236600461443b565b6125cb565b348015610a7357600080fd5b506103c6610a8236600461446f565b6001600160a01b0391909116600090815260fc60209081526040808320938352929052205490565b348015610ab657600080fd5b50610429610ac5366004614771565b6125dd565b348015610ad657600080fd5b50610b67610ae5366004614759565b60fb602052600090815260409020805460018201546002909201546001600160801b0380831693600160801b938490048216939181169291810463ffffffff90811692600160a01b8304821692600160c01b8104831692600160e01b90910481169181811691600160201b82041690600160401b90046001600160a01b03168a565b604080516001600160801b039b8c168152998b1660208b0152979099169688019690965263ffffffff9485166060880152928416608087015290831660a0860152821660c0850152811660e0840152166101008201526001600160a01b03909116610120820152610140016103d0565b348015610be357600080fd5b5061010d54610c029060ff81169061010090046001600160401b031682565b6040805192151583526001600160401b039091166020830152016103d0565b348015610c2d57600080fd5b50610429610c3c36600461495d565b61273c565b348015610c4d57600080fd5b506101085461010954610c6a916001600160a01b03908116911682565b604080516001600160a01b039384168152929091166020830152016103d0565b348015610c9657600080fd5b5060408051808201825260008082526020918201819052805260fe815281518083019092527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af546001600160801b038082168452600160801b90910416908201526106b4565b348015610d0857600080fd5b50610429610d1736600461495d565b612762565b348015610d2857600080fd5b506103c6610d373660046148f1565b61278b565b348015610d4857600080fd5b50610429610d5736600461495d565b61283c565b348015610d6857600080fd5b50610429612864565b348015610d7d57600080fd5b50610429610d8c3660046142d1565b612896565b348015610d9d57600080fd5b50610429610dac36600461495d565b6128fd565b348015610dbd57600080fd5b506103f9610dcc3660046142f4565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b348015610e0657600080fd5b50610429610e153660046142d1565b61291f565b348015610e2657600080fd5b50610429610e35366004614c70565b612978565b348015610e4657600080fd5b50610429610e553660046143d5565b6129c5565b348015610e6657600080fd5b50610429610e753660046142d1565b612a1c565b348015610e8657600080fd5b50610429610e9536600461498f565b612a92565b348015610ea657600080fd5b50610429610eb5366004614b36565b612ec4565b348015610ec657600080fd5b50610f00610ed5366004614759565b61010e6020526000908152604090208054600182015460029092015490916001600160a01b03169083565b604080519384526001600160a01b039092166020840152908201526060016103d0565b60006001600160a01b038316610f935760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060009081526065602090815260408083206001600160a01b03949094168352929052205490565b6000610fc68261306a565b80610fd55750610fd5826130ba565b92915050565b610fe36130df565b604080518082019091526001600160a01b0392831680825291909216602090920182905261010880546001600160a01b0319908116909217905561010980549091169091179055565b61010b805461103a90615a81565b80601f016020809104026020016040519081016040528092919081815260200182805461106690615a81565b80156110b35780601f10611088576101008083540402835291602001916110b3565b820191906000526020600020905b81548152906001019060200180831161109657829003601f168201915b505050505081565b6110c36130df565b61010a546301000000900460ff16156110ef5760405163249fab5d60e01b815260040160405180910390fd5b61138861ffff82161115611116576040516306b7c75960e31b815260040160405180910390fd5b610104805461ffff909216600160d01b0261ffff60d01b19909216919091179055565b6060610101600001805461114c90615a81565b151590506111695760405180602001604052806000815250610fd5565b6101016111758361311a565b604051602001611186929190614d42565b60405160208183030381529060405292915050565b606061010160060180548060200260200160405190810160405280929190818152602001828054801561121557602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116111dc5790505b5050505050905090565b6112276130df565b60408051808201909152600080825260209091015261010880546001600160a01b031990811690915561010980549091169055565b6112646130df565b61126d81613168565b61010a5462010000900460ff16156112985760405163249fab5d60e01b815260040160405180910390fd5b60005b8251811015611321576101016006018382815181106112ca57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018101845560009384529190922060108204018054600f9092166002026101000a61ffff8181021990931692909316929092021790558061131981615ae2565b91505061129b565b505050565b60006113306131d9565b90506001600160a01b03811673271682deb8c4e0901d1a1550ad2e64d568e69909148061137957506001600160a01b0381167386b82972282dd22348374bc63fd21620f7ed847b145b8061139157506097546001600160a01b038281169116145b156113a0576113218383613200565b604051634f631ebf60e01b815260040160405180910390fd5b600082815260ca602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161142e57506040805180820190915260c9546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061144d906001600160601b031687615752565b6114579190615732565b91519350909150505b9250929050565b61146f6131d9565b6001600160a01b0316856001600160a01b03161480611495575061149585610dcc6131d9565b6114b15760405162461bcd60e51b8152600401610f8a9061534e565b6114be85858585856133b2565b5050505050565b6114cd6130df565b6114d681613168565b5061010a805465ff0000000000191665010000000000179055565b6040805160018082528183019092526000916020808301908036833701905050905060008160008151811061153657634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505061155f81611a01565b50565b61156a6130df565b61157381613168565b5061010a805467ff000000000000001916600160381b179055565b6115966130df565b61159f81613168565b61010a54610100900460ff16156115c95760405163249fab5d60e01b815260040160405180910390fd5b610100548263ffffffff1610156115f357604051638a164f6360e01b815260040160405180910390fd5b50610104805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b6116236130df565b61010480546001600160f01b0316600160f01b61ffff8416908102919091179091556116509083906135b9565b5050565b61165c6130df565b61166581613168565b61010a5462010000900460ff16156116905760405163249fab5d60e01b815260040160405180910390fd5b815161132190610107906020850190613f03565b6116ac6130df565b61010a54600160381b900460ff16156116d85760405163249fab5d60e01b815260040160405180910390fd5b82851415806116e75750828114155b15611705576040516306b7c75960e31b815260040160405180910390fd5b6000805b868110156117e757606061179f89898481811061173657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061174b91906142d1565b86868581811061176b57634e487b7160e01b600052603260045260246000fd5b9050602002013589898681811061179257634e487b7160e01b600052603260045260246000fd5b90506020020135846136b6565b8686838181106117bf57634e487b7160e01b600052603260045260246000fd5b90506020020135836117d1919061571a565b92505080806117df90615ae2565b915050611709565b506101045461010054600160a01b90910463ffffffff169061180a90839061571a565b111561182957604051638a164f6360e01b815260040160405180910390fd5b80610100600082825461183c919061571a565b909155505050505050505050565b6114be85856118576131d9565b868686612154565b606081518351146118c45760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610f8a565b600083516001600160401b038111156118ed57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611916578160200160208202803683370190505b50905060005b84518110156119b85761197d85828151811061194857634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061197057634e487b7160e01b600052603260045260246000fd5b6020026020010151610f23565b82828151811061199d57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526119b181615ae2565b905061191c565b509392505050565b6119c86130df565b61010a5460ff16156119ed5760405163249fab5d60e01b815260040160405180910390fd5b805161165090610101906020840190613fac565b73365110b34b46927b2158e07e6d3c6d4802e032f06360f0e59661010160fe60ff611a346097546001600160a01b031690565b866040518663ffffffff1660e01b8152600401611a55959493929190615476565b60006040518083038186803b158015611a6d57600080fd5b505af41580156114be573d6000803e3d6000fd5b611a896137d7565b611a936000613850565b565b61010180548190611aa590615a81565b80601f0160208091040260200160405190810160405280929190818152602001828054611ad190615a81565b8015611b1e5780601f10611af357610100808354040283529160200191611b1e565b820191906000526020600020905b815481529060010190602001808311611b0157829003601f168201915b5050505060018301546002840154600385015460408051808201825260048801805461ffff908116835260058a01805485516020808302820181019097528181529a9b6001600160a01b03998a169b988a169a5098871698600160a01b880463ffffffff1698600160c01b8904851698600160d01b8104861698600160e01b8204871698600160f01b90920490961696929590949293818601939160009084015b82821015611c02576000848152602090819020604080518082019091529084015461ffff8082168352620100009091041681830152825260019092019101611bbf565b505050508152505090508a565b611c176130df565b610104805461ffff909216600160c01b0261ffff60c01b19909216919091179055565b611c426130df565b611c4b81613168565b5061010a805461ff001916610100179055565b610108546001600160a01b0316611c8857604051631dc68aa160e11b815260040160405180910390fd5b808314611ca8576040516306b7c75960e31b815260040160405180910390fd5b6000611cb26131d9565b90506000805b85811015611e3957610109546000906001600160a01b0316611cdc5761dead611cea565b610109546001600160a01b03165b610108549091506060906001600160a01b031663f242432a86848c8c88818110611d2457634e487b7160e01b600052603260045260246000fd5b905060200201358b8b89818110611d4b57634e487b7160e01b600052603260045260246000fd5b90506020020135866040518663ffffffff1660e01b8152600401611d73959493929190614e20565b600060405180830381600087803b158015611d8d57600080fd5b505af1158015611da1573d6000803e3d6000fd5b50505050611df0858a8a86818110611dc957634e487b7160e01b600052603260045260246000fd5b9050602002013589898781811061179257634e487b7160e01b600052603260045260246000fd5b868684818110611e1057634e487b7160e01b600052603260045260246000fd5b9050602002013584611e22919061571a565b935050508080611e3190615ae2565b915050611cb8565b506101045461010054600160a01b90910463ffffffff1690611e5c90839061571a565b1115611e7b57604051638a164f6360e01b815260040160405180910390fd5b806101006000828254611e8e919061571a565b9091555050505050505050565b611ea36130df565b60408051610160810190915280611ebd6020840184614b68565b6001600160801b03168152602090810190611eda90840184614b68565b6001600160801b0316815260200160006001600160801b03168152602001826020016020810190611f0b9190614c11565b63ffffffff168152602001611f266060840160408501614c11565b63ffffffff168152602001611f416080840160608501614c11565b63ffffffff168152602001611f5c60a0840160808501614c11565b63ffffffff16815260006020820152604001611f7e60c0840160a08501614c11565b63ffffffff168152602001611f9960e0840160c085016142d1565b6001600160a01b03168152602001611fb460e084018461562e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093909452505085815260fb60209081526040918290208451858301516001600160801b03918216600160801b918316820217835593860151600183018054606089015160808a015160a08b015160c08c0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e085015160028201805461010088015161012089015193871667ffffffffffffffff1990921691909117600160201b919096160294909417600160401b600160e01b031916600160401b6001600160a01b039092169190910217909255610140840151805192935061211f9260038501929190910190613f03565b505060405183915084907fe9a0c17645ed78ccc9996259f00297ffc75e6b9d22cd605ccc9992cc8ca3f4c190600090a3505050565b8535600090815260fb6020526040902060028101546001600160201b90910463ffffffff16111561219e57600281015461219b90600160201b900463ffffffff1687615752565b95505b600060405180608001604052806121bd6097546001600160a01b031690565b6001600160a01b03168152602001866001600160a01b0316815260200188815260200161010054815250905073365110b34b46927b2158e07e6d3c6d4802e032f0633e737b11836101018b60fc60fd8a8a896040518963ffffffff1660e01b81526004016122329897969594939291906154e4565b60006040518083038186803b15801561224a57600080fd5b505af415801561225e573d6000803e3d6000fd5b505061010d5460ff161591506122db905057600061227a6138a2565b604080516060810182528b3581526001600160a01b038a811660208084019182528385018e8152600096875261010e909152939094209151825592516001820180546001600160a01b03191691909416179092555160029091015550612453565b6060600073365110b34b46927b2158e07e6d3c6d4802e032f0635ec01e4d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561232357600080fd5b505af4158015612337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235b9190614b9e565b60405163101d90c960e31b815290915073365110b34b46927b2158e07e6d3c6d4802e032f0906380ec8648906123a0906101079060038901908e908790600401614ead565b60006040518083038186803b1580156123b857600080fd5b505af41580156123cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123f491908101906145f6565b915060005b825181101561244f57606061243c8a85848151811061242857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff166001846136b6565b508061244781615ae2565b9150506123f9565b5050505b866101006000828254612466919061571a565b9091555050600182015463ffffffff600160e01b82048116600160c01b9092041610156124e4578660fc600061249a6131d9565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a60000135815260200190815260200160002060008282546124de919061571a565b90915550505b600182015463ffffffff600160e01b90910481161015612524578735600090815260fd60205260408120805489929061251e90849061571a565b90915550505b6040516329ba982960e21b815260048101839052610101602482015260fe604482015260ff60648201526001600160a01b038616608482015260a4810188905273365110b34b46927b2158e07e6d3c6d4802e032f09063a6ea60a49060c40160006040518083038186803b15801561259b57600080fd5b505af41580156125af573d6000803e3d6000fd5b505050505050505050505050565b61010c805461103a90615a81565b6116506125d66131d9565b8383613982565b6125e56130df565b42816060015163ffffffff1610156126045763ffffffff421660608201525b600083815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b919096160294909417600160401b600160e01b031916600160401b6001600160a01b039092169190910217909255610140830151805184939261211f926003850192910190613f03565b6127446130df565b61274d81613168565b5061010a805462ff0000191662010000179055565b61276a6130df565b61277381613168565b5061010a805464ff000000001916600160201b179055565b600083815260fb60205260408082209051633e09927360e21b815260048101829052610105602482015260448101859052831515606482015273365110b34b46927b2158e07e6d3c6d4802e032f09063f82649cc9060840160206040518083038186803b1580156127fb57600080fd5b505af415801561280f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128339190614b9e565b95945050505050565b6128446130df565b61284d81613168565b5061010a805463ff00000019166301000000179055565b61286c6130df565b60408051808201909152600080825260209091015261010d805468ffffffffffffffffff19169055565b7386b82972282dd22348374bc63fd21620f7ed847b6128b36131d9565b6001600160a01b0316146128da5760405163016bdfed60e71b815260040160405180910390fd5b61010480546001600160a01b0319166001600160a01b0392909216919091179055565b6129056130df565b61290e81613168565b5061010a805460ff19166001179055565b6129276130df565b61010a5465010000000000900460ff16156129555760405163249fab5d60e01b815260040160405180910390fd5b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b6129806130df565b6040805180820190915260018082526001600160401b0392909216602090910181905261010d805468ffffffffffffffffff1916610100909202919091179091179055565b6129cd6131d9565b6001600160a01b0316856001600160a01b031614806129f357506129f385610dcc6131d9565b612a0f5760405162461bcd60e51b8152600401610f8a9061534e565b6114be8585858585613a63565b612a246137d7565b6001600160a01b038116612a895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f8a565b61155f81613850565b600054610100900460ff1615808015612ab25750600054600160ff909116105b80612acc5750303b158015612acc575060005460ff166001145b612b2f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610f8a565b6000805460ff191660011790558015612b52576000805461ff0019166101001790555b8451612b669061010b906020880190613fac565b508351612b7b9061010c906020870190613fac565b50612b9460405180602001604052806000815250613b9c565b61010f80546001600160a01b03191673271682deb8c4e0901d1a1550ad2e64d568e69909179055611388612bce60e0850160c08601614b82565b61ffff161180612bf35750611388612bed610100850160e08601614b82565b61ffff16115b80612c1357506101f4612c0d610100850160e08601614b82565b61ffff16105b80612c3e5750611388612c2a6101208501856156b9565b612c38906020810190614b82565b61ffff16115b80612c6157506000612c5660408501602086016142d1565b6001600160a01b0316145b80612c7d5750612c7760c0840160a08501614b82565b61ffff16155b15612c9b576040516306b7c75960e31b815260040160405180910390fd5b60015b612cac6101208501856156b9565b612cba9060208101906155e7565b9050811015612e0757611388612cd46101208601866156b9565b612ce29060208101906155e7565b83818110612d0057634e487b7160e01b600052603260045260246000fd5b9050604002016020016020810190612d189190614b82565b61ffff161180612dd75750612d316101208501856156b9565b612d3f9060208101906155e7565b612d4a600184615771565b818110612d6757634e487b7160e01b600052603260045260246000fd5b612d7d9260206040909202019081019150614b82565b61ffff16612d8f6101208601866156b9565b612d9d9060208101906155e7565b83818110612dbb57634e487b7160e01b600052603260045260246000fd5b612dd19260206040909202019081019150614b82565b61ffff16115b15612df5576040516306b7c75960e31b815260040160405180910390fd5b80612dff81615ae2565b915050612c9e565b5082610101612e168282615c11565b905050612e21613bcc565b610103546001600160a01b031615612e5e576101035461010454612e59916001600160a01b031690600160f01b900461ffff1661161b565b612e78565b61010454612e78908390600160f01b900461ffff1661161b565b80156114be576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b612ecc6130df565b61010a54600160201b900460ff1615612ef85760405163249fab5d60e01b815260040160405180910390fd5b611388612f086020830183614b82565b61ffff161115612f2b576040516306b7c75960e31b815260040160405180910390fd5b60015b612f3b60208301836155e7565b905081101561305b57611388612f5460208401846155e7565b83818110612f7257634e487b7160e01b600052603260045260246000fd5b9050604002016020016020810190612f8a9190614b82565b61ffff16118061302b5750612fa260208301836155e7565b612fad600184615771565b818110612fca57634e487b7160e01b600052603260045260246000fd5b612fe09260206040909202019081019150614b82565b61ffff16612ff160208401846155e7565b8381811061300f57634e487b7160e01b600052603260045260246000fd5b6130259260206040909202019081019150614b82565b61ffff16115b15613049576040516306b7c75960e31b815260040160405180910390fd5b8061305381615ae2565b915050612f2e565b50806101056113218282615d9c565b60006001600160e01b03198216636cdb3d1360e11b148061309b57506001600160e01b031982166303a24d0760e21b145b80610fd557506301ffc9a760e01b6001600160e01b0319831614610fd5565b60006001600160e01b0319821663152a902d60e11b1480610fd55750610fd58261306a565b6097546001600160a01b03166130f36131d9565b6001600160a01b031614611a93576040516330cd747160e01b815260040160405180910390fd5b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061315157613156565b613134565b50819003601f19909101908152919050565b604051663337b932bb32b960c91b602082015260270160405160208183030381529060405280519060200120816040516020016131a59190614d26565b604051602081830303815290604052805190602001201461155f57604051635ee88f9760e01b815260040160405180910390fd5b600033736bc558a6dc48defa0e7022713c23d65ab26e4fa7146131fb57503390565b503290565b600082815261010e602090815260409182902082516060810184528154815260018201546001600160a01b031692810192909252600201549181018290529061325c576040516302e8145360e61b815260040160405180910390fd5b606073365110b34b46927b2158e07e6d3c6d4802e032f06380ec864861010160060160fb6000866000015181526020019081526020016000206003018560400151876000815181106132be57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518563ffffffff1660e01b81526004016132e59493929190614ead565b60006040518083038186803b1580156132fd57600080fd5b505af4158015613311573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261333991908101906145f6565b905060005b8151811015613384576060613371846020015184848151811061242857634e487b7160e01b600052603260045260246000fd5b508061337c81615ae2565b91505061333e565b50505060009182525061010e602052604081208181556001810180546001600160a01b031916905560020155565b81518351146134145760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610f8a565b6001600160a01b03841661343a5760405162461bcd60e51b8152600401610f8a9061539c565b60006134446131d9565b905060005b845181101561354b57600085828151811061347457634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008583815181106134a057634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526065835260408082206001600160a01b038e1683529093529190912054909150818110156134f15760405162461bcd60e51b8152600401610f8a906153e1565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b1682528120805484929061353090849061571a565b925050819055505050508061354490615ae2565b9050613449565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161359b9291906151eb565b60405180910390a46135b1818787878787613bfb565b505050505050565b6127106001600160601b03821611156136275760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610f8a565b6001600160a01b03821661367d5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610f8a565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760c955565b6001600160a01b0384166137165760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610f8a565b60006137206131d9565b9050600061372d85613d66565b9050600061373a85613d66565b905060008681526065602090815260408083206001600160a01b038b1684529091528120805487929061376e90849061571a565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46137ce83600089898989613dbf565b50505050505050565b6137df6131d9565b6001600160a01b03166137fa6097546001600160a01b031690565b6001600160a01b031614611a935760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f8a565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61010f5461010d546040516305d3b1d360e41b81527f8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef600482018190526101009092046001600160401b03166024820152600560448201819052622625a06064830181905260016084840152600094919290916001600160a01b031690635d3b1d309060a401602060405180830381600087803b15801561394257600080fd5b505af1158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190614b9e565b935050505090565b816001600160a01b0316836001600160a01b031614156139f65760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610f8a565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b038416613a895760405162461bcd60e51b8152600401610f8a9061539c565b6000613a936131d9565b90506000613aa085613d66565b90506000613aad85613d66565b905060008681526065602090815260408083206001600160a01b038c16845290915290205485811015613af25760405162461bcd60e51b8152600401610f8a906153e1565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290613b3190849061571a565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613b91848a8a8a8a8a613dbf565b505050505050505050565b600054610100900460ff16613bc35760405162461bcd60e51b8152600401610f8a9061542b565b61155f81613e89565b600054610100900460ff16613bf35760405162461bcd60e51b8152600401610f8a9061542b565b611a93613eb9565b6001600160a01b0384163b156135b15760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613c3f9089908990889088908890600401614dc2565b602060405180830381600087803b158015613c5957600080fd5b505af1925050508015613c89575060408051601f3d908101601f19168201909252613c8691810190614941565b60015b613d3657613c95615b50565b806308c379a01415613ccf5750613caa615b68565b80613cb55750613cd1565b8060405162461bcd60e51b8152600401610f8a9190615210565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610f8a565b6001600160e01b0319811663bc197c8160e01b146137ce5760405162461bcd60e51b8152600401610f8a90615306565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613dae57634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156135b15760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613e039089908990889088908890600401614e20565b602060405180830381600087803b158015613e1d57600080fd5b505af1925050508015613e4d575060408051601f3d908101601f19168201909252613e4a91810190614941565b60015b613e5957613c95615b50565b6001600160e01b0319811663f23a6e6160e01b146137ce5760405162461bcd60e51b8152600401610f8a90615306565b600054610100900460ff16613eb05760405162461bcd60e51b8152600401610f8a9061542b565b61155f81613ef0565b600054610100900460ff16613ee05760405162461bcd60e51b8152600401610f8a9061542b565b611a93613eeb6131d9565b613850565b8051611650906067906020840190613fac565b82805482825590600052602060002090600f01601090048101928215613f9c5791602002820160005b83821115613f6c57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302613f2c565b8015613f9a5782816101000a81549061ffff0219169055600201602081600101049283019260010302613f6c565b505b50613fa8929150614020565b5090565b828054613fb890615a81565b90600052602060002090601f016020900481019282613fda5760008555613f9c565b82601f10613ff357805160ff1916838001178555613f9c565b82800160010185558215613f9c579182015b82811115613f9c578251825591602001919060010190614005565b5b80821115613fa85760008155600101614021565b803561404081615ec0565b919050565b60008083601f840112614056578182fd5b5081356001600160401b0381111561406c578182fd5b6020830191508360208260051b850101111561146057600080fd5b600082601f830112614097578081fd5b813560206140a4826156f7565b6040516140b18282615ab6565b8381528281019150858301600585901b870184018810156140d0578586fd5b855b858110156140f75781356140e581615ec0565b845292840192908401906001016140d2565b5090979650505050505050565b600082601f830112614114578081fd5b81356020614121826156f7565b60405161412e8282615ab6565b8381528281019150858301600585901b8701840188101561414d578586fd5b855b858110156140f757813561416281615eeb565b8452928401929084019060010161414f565b600082601f830112614184578081fd5b81356020614191826156f7565b60405161419e8282615ab6565b8381528281019150858301600585901b870184018810156141bd578586fd5b855b858110156140f7578135845292840192908401906001016141bf565b8035801515811461404057600080fd5b60008083601f8401126141fc578182fd5b5081356001600160401b03811115614212578182fd5b60208301915083602082850101111561146057600080fd5b600082601f83011261423a578081fd5b81356001600160401b0381111561425357614253615b13565b60405161426a601f8301601f191660200182615ab6565b81815284602083860101111561427e578283fd5b816020850160208301379081016020019190915292915050565b6000604082840312156142a9578081fd5b50919050565b80356001600160801b038116811461404057600080fd5b803561404081615efb565b6000602082840312156142e2578081fd5b81356142ed81615ec0565b9392505050565b60008060408385031215614306578081fd5b823561431181615ec0565b9150602083013561432181615ec0565b809150509250929050565b600080600080600060a08688031215614343578081fd5b853561434e81615ec0565b9450602086013561435e81615ec0565b935060408601356001600160401b0380821115614379578283fd5b61438589838a01614174565b9450606088013591508082111561439a578283fd5b6143a689838a01614174565b935060808801359150808211156143bb578283fd5b506143c88882890161422a565b9150509295509295909350565b600080600080600060a086880312156143ec578283fd5b85356143f781615ec0565b9450602086013561440781615ec0565b9350604086013592506060860135915060808601356001600160401b0381111561442f578182fd5b6143c88882890161422a565b6000806040838503121561444d578182fd5b823561445881615ec0565b9150614466602084016141db565b90509250929050565b60008060408385031215614481578182fd5b823561448c81615ec0565b946020939093013593505050565b600080604083850312156144ac578182fd5b82356144b781615ec0565b9150602083013561432181615eeb565b600080600080600080606087890312156144df578384fd5b86356001600160401b03808211156144f5578586fd5b6145018a838b01614045565b90985096506020890135915080821115614519578586fd5b6145258a838b01614045565b9096509450604089013591508082111561453d578283fd5b5061454a89828a01614045565b979a9699509497509295939492505050565b60006020828403121561456d578081fd5b81356001600160401b03811115614582578182fd5b61458e84828501614087565b949350505050565b600080604083850312156145a8578182fd5b82356001600160401b03808211156145be578384fd5b6145ca86838701614087565b935060208501359150808211156145df578283fd5b506145ec85828601614174565b9150509250929050565b60006020808385031215614608578182fd5b82516001600160401b0381111561461d578283fd5b8301601f8101851361462d578283fd5b8051614638816156f7565b6040516146458282615ab6565b8281528481019150838501600584901b85018601891015614664578687fd5b8694505b8385101561468f57805161467b81615eeb565b835260019490940193918501918501614668565b50979650505050505050565b600080604083850312156146ad578182fd5b82356001600160401b03808211156146c3578384fd5b6146cf86838701614104565b935060208501359150808211156146e4578283fd5b506145ec8582860161422a565b60008060008060408587031215614706578182fd5b84356001600160401b038082111561471c578384fd5b61472888838901614045565b90965094506020870135915080821115614740578384fd5b5061474d87828801614045565b95989497509550505050565b60006020828403121561476a578081fd5b5035919050565b600080600060608486031215614785578081fd5b833592506020840135915060408401356001600160401b03808211156147a9578283fd5b9085019061016082880312156147bd578283fd5b6147c56156ce565b6147ce836142af565b81526147dc602084016142af565b60208201526147ed604084016142af565b60408201526147fe606084016142c6565b606082015261480f608084016142c6565b608082015261482060a084016142c6565b60a082015261483160c084016142c6565b60c082015261484260e084016142c6565b60e08201526101006148558185016142c6565b90820152610120614867848201614035565b90820152610140838101358381111561487e578586fd5b61488a8a828701614104565b8284015250508093505050509250925092565b6000806000606084860312156148b1578081fd5b833592506020840135915060408401356001600160401b038111156148d4578182fd5b840161010081870312156148e6578182fd5b809150509250925092565b600080600060608486031215614905578081fd5b833592506020840135915061491c604085016141db565b90509250925092565b600060208284031215614936578081fd5b81356142ed81615ed5565b600060208284031215614952578081fd5b81516142ed81615ed5565b60006020828403121561496e578081fd5b81356001600160401b03811115614983578182fd5b61458e8482850161422a565b600080600080608085870312156149a4578182fd5b84356001600160401b03808211156149ba578384fd5b6149c68883890161422a565b955060208701359150808211156149db578384fd5b6149e78883890161422a565b945060408701359150808211156149fc578384fd5b5085016101608188031215614a0f578283fd5b91506060850135614a1f81615ec0565b939692955090935050565b60008060008060008060a08789031215614a42578384fd5b86356001600160401b0380821115614a58578586fd5b614a648a838b01614298565b97506020890135965060408901359150614a7d82615ec0565b909450606088013590614a8f82615ec0565b90935060808801359080821115614aa4578384fd5b5061454a89828a016141eb565b600080600080600060808688031215614ac8578283fd5b85356001600160401b0380821115614ade578485fd5b614aea89838a01614298565b96506020880135955060408801359150614b0382615ec0565b90935060608701359080821115614b18578283fd5b50614b25888289016141eb565b969995985093965092949392505050565b600060208284031215614b47578081fd5b81356001600160401b03811115614b5c578182fd5b61458e84828501614298565b600060208284031215614b79578081fd5b6142ed826142af565b600060208284031215614b93578081fd5b81356142ed81615eeb565b600060208284031215614baf578081fd5b5051919050565b60008060408385031215614bc8578182fd5b8235915060208301356001600160401b03811115614be4578182fd5b6145ec85828601614174565b60008060408385031215614c02578182fd5b50508035926020909101359150565b600060208284031215614c22578081fd5b81356142ed81615efb565b60008060408385031215614c3f578182fd5b8235614c4a81615efb565b915060208301356001600160401b03811115614c64578182fd5b6145ec8582860161422a565b600060208284031215614c81578081fd5b81356001600160401b03811681146142ed578182fd5b6000815180845260208085019450808401835b83811015614cc657815187529582019590820190600101614caa565b509495945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614d12816020860160208601615971565b601f01601f19169290920160200192915050565b60008251614d38818460208701615971565b9190910192915050565b6000808454614d5081615a81565b60018281168015614d685760018114614d7957614da5565b60ff19841687528287019450614da5565b8886526020808720875b85811015614d9c5781548a820152908401908201614d83565b50505082870194505b505050508351614db9818360208801615971565b01949350505050565b6001600160a01b0386811682528516602082015260a060408201819052600090614dee90830186614c97565b8281036060840152614e008186614c97565b90508281036080840152614e148185614cfa565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090614e5a90830184614cfa565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614ea157835161ffff1683529284019291840191600101614e81565b50909695505050505050565b6000608080830187845260208281860152818854614ecf818590815260200190565b60008b81526020902094509150855b81600f8201101561501c57845461ffff8082168552601082901c8116868601526040614f1381870183858a1c1661ffff169052565b6060614f29818801848660301c1661ffff169052565b61ffff84831c841616878b015260a09150614f4e828801848660501c1661ffff169052565b60c0614f638189018587851c1661ffff169052565b60e09150614f7b828901858760701c1661ffff169052565b61ffff858c1c851616610100890152614fa06101208901858760901c1661ffff169052565b61ffff85841c851616610140890152614fc56101608901858760b01c1661ffff169052565b61ffff85821c85161661018089015250614feb6101a08801848660d01c1661ffff169052565b83901c9190911661ffff166101c08601525060f01c6101e08401526001949094019361020090920191601001614ede565b935493818110156150365761ffff85168352918301916001015b8181101561505157601085901c61ffff168352918301916001015b8181101561506a5784841c61ffff168352918301916001015b8181101561508557603085901c61ffff168352918301916001015b818110156150a057604085901c61ffff168352918301916001015b818110156150bb57605085901c61ffff168352918301916001015b818110156150d657606085901c61ffff168352918301916001015b818110156150f157607085901c61ffff168352918301916001015b8181101561510a5784861c61ffff168352918301916001015b8181101561512557609085901c61ffff168352918301916001015b818110156151405760a085901c61ffff168352918301916001015b8181101561515b5760b085901c61ffff168352918301916001015b818110156151765760c085901c61ffff168352918301916001015b818110156151915760d085901c61ffff168352918301916001015b818110156151ac5760e085901c61ffff168352918301916001015b818110156151c05760f085901c8352918301915b50506040860197909752505050506060015292915050565b6020815260006142ed6020830184614c97565b6040815260006151fe6040830185614c97565b82810360208401526128338185614c97565b6020815260006142ed6020830184614cfa565b60006101408083526152378184018e614cfa565b9050602060018060a01b03808e16828601526040818e1681870152818d16606087015263ffffffff8c16608087015261ffff9150818b1660a0870152818a1660c087015281891660e087015281881661010087015285840361012087015280840182885116855283880151828587015281815180845260608801915086830197508893505b808410156152ec5787518051871683528781015187168884015297870197600194909401939250908401906152bc565b50809750505050505050509b9a5050505050505050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060a082018783526020878185015286604085015260018060a01b03808716606086015260a0608086015282865180855260c0870191508388019450855b818110156154d35785518416835294840194918401916001016154b5565b50909b9a5050505050505050505050565b60006101408a8352896020840152806040840152883581840152506020880135601e19893603018112615515578182fd5b880180356001600160401b0381111561552c578283fd5b8060051b8036038b131561553e578384fd5b604061016086015261018085018290526101a06001600160fb1b03831115615564578485fd5b816020850182880137818601935080840192508483528a6060870152896080870152808685030160a0870152505061559d818789614cd1565b85516001600160a01b0390811660c087015260208701511660e08601526040860151610100860152606086015161012086015292506155da915050565b9998505050505050505050565b6000808335601e198436030181126155fd578283fd5b8301803591506001600160401b03821115615616578283fd5b6020019150600681901b360382131561146057600080fd5b6000808335601e19843603018112615644578283fd5b8301803591506001600160401b0382111561565d578283fd5b6020019150600581901b360382131561146057600080fd5b6000808335601e1984360301811261568b578283fd5b8301803591506001600160401b038211156156a4578283fd5b60200191503681900382131561146057600080fd5b60008235603e19833603018112614d38578182fd5b60405161016081016001600160401b03811182821017156156f1576156f1615b13565b60405290565b60006001600160401b0382111561571057615710615b13565b5060051b60200190565b6000821982111561572d5761572d615afd565b500190565b60008261574d57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561576c5761576c615afd565b500290565b60008282101561578357615783615afd565b500390565b5b818110156116505760008155600101615789565b600160401b8311156157b1576157b1615b13565b80548382558084101561580a57816000526020600020600f850160041c8101601e8660011b1680156157f4576000198083018054828460200360031b1c16815550505b50615807600f840160041c830182615788565b50505b506000818152602081208391805b868110156137ce5761584a61582c85615b36565b845461ffff600386901b81811b801990931693909116901b16178455565b602084019350600282019150601e82111561586a57600091506001830192505b600101615818565b6001600160401b0383111561588957615889615b13565b6158938154615a81565b600080601f8611601f8411818117156158b25760008681526020902092505b80156158e157601f880160051c830160208910156158cd5750825b6158df601f870160051c850182615788565b505b508060018114615915576000945087156158fc578387013594505b600188901b60001960038a901b1c198616178655615967565b601f198816945082845b8681101561593f578886013582556020958601956001909201910161591f565b508886101561595c5760001960f88a60031b161c19858901351681555b5060018860011b0186555b5050505050505050565b60005b8381101561598c578181015183820152602001615974565b8381111561599b576000848401525b50505050565b81356159ac81615eeb565b815461ffff191661ffff82161782555060018082016020840135601e198536030181126159d857600080fd5b840180356001600160401b038111156159f057600080fd5b6020820191508060061b3603821315615a0857600080fd5b600160401b811115615a1c57615a1c615b13565b825481845580821015615a51576000848152602081208381019083015b80821015615a4d5782825590870190615a39565b5050505b50600092835260208320925b818110156137ce57615a6f8385615e7c565b92840192604092909201918401615a5d565b600181811c90821680615a9557607f821691505b602082108114156142a957634e487b7160e01b600052602260045260246000fd5b601f8201601f191681016001600160401b0381118282101715615adb57615adb615b13565b6040525050565b6000600019821415615af657615af6615afd565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610fd581615ec0565b60008135610fd581615eeb565b60008135610fd581615efb565b600060033d1115615b6557600481823e5160e01c5b90565b600060443d1015615b765790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615ba557505050505090565b8285019150815181811115615bbd5750505050505090565b843d8701016020828501011115615bd75750505050505090565b615be660208286010187615ab6565b509095945050505050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b615c1b8283615675565b615c26818385615872565b5050615c40615c3760208401615b29565b60018301615bf1565b615c58615c4f60408401615b29565b60028301615bf1565b60038101615c71615c6b60608501615b29565b82615bf1565b615ca4615c8060808501615b43565b82805463ffffffff60a01b191660a09290921b63ffffffff60a01b16919091179055565b615cd3615cb360a08501615b36565b82805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b615d02615ce260c08501615b36565b82805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b615d31615d1160e08501615b36565b82805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b615d65615d416101008501615b36565b8280546001600160f01b031660f09290921b6001600160f01b031916919091179055565b50615d80615d776101208401846156b9565b600483016159a1565b615d8e61014083018361562e565b61599b81836006860161579d565b8135615da781615eeb565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615dd357600080fd5b840180356001600160401b03811115615deb57600080fd5b6020820191508060061b3603821315615e0357600080fd5b600160401b811115615e1757615e17615b13565b825481845580821015615e4c576000848152602081208381019083015b80821015615e485782825590870190615e34565b5050505b50600092835260208320925b818110156137ce57615e6a8385615e7c565b92840192604092909201918401615e58565b8135615e8781615eeb565b815461ffff191661ffff8216178255506020820135615ea581615eeb565b815463ffff0000191660109190911b63ffff00001617905550565b6001600160a01b038116811461155f57600080fd5b6001600160e01b03198116811461155f57600080fd5b61ffff8116811461155f57600080fd5b63ffffffff8116811461155f57600080fdfea2646970667358221220b95ce233f6ee2c2cc7d96fe0e9d03e15d7f97eceb9ce2239883b9fecc3406a5464736f6c63430008040033
Deployed Bytecode
0x6080604052600436106103a15760003560e01c806379b004db116101e7578063b828aa831161010d578063e985e9c5116100a0578063f2fde38b1161006f578063f2fde38b14610e5a578063f7d1f2ca14610e7a578063fd614f2a14610e9a578063fec5176e14610eba57600080fd5b8063e985e9c514610db1578063ead0055314610dfa578063ed42802714610e1a578063f242432a14610e3a57600080fd5b8063ce216e2f116100dc578063ce216e2f14610d3c578063d25e2cd614610d5c578063d71d8d2314610d71578063de6cd0db14610d9157600080fd5b8063b828aa8314610c41578063bedcf00314610c8a578063c7494df714610cfc578063caf3e53214610d1c57600080fd5b8063978a450911610185578063a402628411610154578063a402628414610aaa578063a5aa4aa414610aca578063aa85448114610bd7578063b518e16a14610c2157600080fd5b8063978a4509146109d05780639a7a973c14610a1a578063a22cb46514610a47578063a3edb86a14610a6757600080fd5b806384a0b9eb116101c157806384a0b9eb1461096a5780638da5cb5b1461098a5780639564e8e4146109a857806395d89b41146109bb57600080fd5b806379b004db1461090a5780637c5d0a081461092a5780637d08782d1461094a57600080fd5b80632eb2c2d6116102cc578063493b2d211161026a57806355f804b31161023957806355f804b31461088a5780635ecb16cd146108aa578063715018a6146108ca57806379502c55146108df57600080fd5b8063493b2d21146107ef5780634a21a2df1461080f5780634bde38c8146108225780634e1273f41461085d57600080fd5b80633fb3b20a116102a65780633fb3b20a1461076f578063400e3db91461078f5780634331f639146107af57806347dd4636146107cf57600080fd5b80632eb2c2d61461071a57806332f7c6d41461073a5780633ccfd60b1461075a57600080fd5b806310566ef6116103445780631fe543e3116103135780631fe543e3146105bc57806321d5bf24146105dc57806327a59437146106435780632a55205a146106db57600080fd5b806310566ef6146104af5780631069143a146104c457806318160ddd1461058557806318e201121461059c57600080fd5b806306fdde031161038057806306fdde031461042b5780630c6f910b1461044d5780630e89341c1461046d578063104e99291461048d57600080fd5b8062fdd58e146103a657806301ffc9a7146103d957806303be0ce614610409575b600080fd5b3480156103b257600080fd5b506103c66103c136600461446f565b610f23565b6040519081526020015b60405180910390f35b3480156103e557600080fd5b506103f96103f4366004614925565b610fbb565b60405190151581526020016103d0565b34801561041557600080fd5b506104296104243660046142f4565b610fdb565b005b34801561043757600080fd5b5061044061102c565b6040516103d09190615210565b34801561045957600080fd5b50610429610468366004614b82565b6110bb565b34801561047957600080fd5b50610440610488366004614759565b611139565b34801561049957600080fd5b506104a261119b565b6040516103d09190614e65565b3480156104bb57600080fd5b5061042961121f565b3480156104d057600080fd5b5061010a546105339060ff80821691610100810482169162010000820481169163010000008104821691600160201b820481169165010000000000810482169166010000000000008204811691600160381b8104821691600160401b9091041689565b604080519915158a5297151560208a01529515159688019690965292151560608701529015156080860152151560a0850152151560c084015290151560e08301521515610100820152610120016103d0565b34801561059157600080fd5b506103c66101005481565b3480156105a857600080fd5b506104296105b736600461469b565b61125c565b3480156105c857600080fd5b506104296105d7366004614bb6565b611326565b3480156105e857600080fd5b5061062b6105f73660046142f4565b6001600160a01b03918216600090815260ff602090815260408083209390941682529190915220546001600160801b031690565b6040516001600160801b0390911681526020016103d0565b34801561064f57600080fd5b506106b461065e3660046142d1565b6040805180820190915260008082526020820152506001600160a01b0316600090815260fe60209081526040918290208251808401909352546001600160801b038082168452600160801b909104169082015290565b6040805182516001600160801b0390811682526020938401511692810192909252016103d0565b3480156106e757600080fd5b506106fb6106f6366004614bf0565b6113b9565b604080516001600160a01b0390931683526020830191909152016103d0565b34801561072657600080fd5b5061042961073536600461432c565b611467565b34801561074657600080fd5b5061042961075536600461495d565b6114c5565b34801561076657600080fd5b506104296114f1565b34801561077b57600080fd5b5061042961078a36600461495d565b611562565b34801561079b57600080fd5b506104296107aa366004614c2d565b61158e565b3480156107bb57600080fd5b506104296107ca36600461449a565b61161b565b3480156107db57600080fd5b506104296107ea36600461469b565b611654565b3480156107fb57600080fd5b5061042961080a3660046144c7565b6116a4565b61042961081d366004614ab1565b61184a565b34801561082e57600080fd5b507386b82972282dd22348374bc63fd21620f7ed847b5b6040516001600160a01b0390911681526020016103d0565b34801561086957600080fd5b5061087d610878366004614596565b61185f565b6040516103d091906151d8565b34801561089657600080fd5b506104296108a536600461495d565b6119c0565b3480156108b657600080fd5b506104296108c536600461455c565b611a01565b3480156108d657600080fd5b50610429611a81565b3480156108eb57600080fd5b506108f4611a95565b6040516103d09a99989796959493929190615223565b34801561091657600080fd5b50610429610925366004614b82565b611c0f565b34801561093657600080fd5b5061042961094536600461495d565b611c3a565b34801561095657600080fd5b506104296109653660046146f1565b611c5e565b34801561097657600080fd5b5061042961098536600461489d565b611e9b565b34801561099657600080fd5b506097546001600160a01b0316610845565b6104296109b6366004614a2a565b612154565b3480156109c757600080fd5b506104406125bd565b3480156109dc57600080fd5b5061062b6109eb3660046142d1565b6001600160a01b0316600090815260ff602090815260408083208380529091529020546001600160801b031690565b348015610a2657600080fd5b506103c6610a35366004614759565b600090815260fd602052604090205490565b348015610a5357600080fd5b50610429610a6236600461443b565b6125cb565b348015610a7357600080fd5b506103c6610a8236600461446f565b6001600160a01b0391909116600090815260fc60209081526040808320938352929052205490565b348015610ab657600080fd5b50610429610ac5366004614771565b6125dd565b348015610ad657600080fd5b50610b67610ae5366004614759565b60fb602052600090815260409020805460018201546002909201546001600160801b0380831693600160801b938490048216939181169291810463ffffffff90811692600160a01b8304821692600160c01b8104831692600160e01b90910481169181811691600160201b82041690600160401b90046001600160a01b03168a565b604080516001600160801b039b8c168152998b1660208b0152979099169688019690965263ffffffff9485166060880152928416608087015290831660a0860152821660c0850152811660e0840152166101008201526001600160a01b03909116610120820152610140016103d0565b348015610be357600080fd5b5061010d54610c029060ff81169061010090046001600160401b031682565b6040805192151583526001600160401b039091166020830152016103d0565b348015610c2d57600080fd5b50610429610c3c36600461495d565b61273c565b348015610c4d57600080fd5b506101085461010954610c6a916001600160a01b03908116911682565b604080516001600160a01b039384168152929091166020830152016103d0565b348015610c9657600080fd5b5060408051808201825260008082526020918201819052805260fe815281518083019092527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af546001600160801b038082168452600160801b90910416908201526106b4565b348015610d0857600080fd5b50610429610d1736600461495d565b612762565b348015610d2857600080fd5b506103c6610d373660046148f1565b61278b565b348015610d4857600080fd5b50610429610d5736600461495d565b61283c565b348015610d6857600080fd5b50610429612864565b348015610d7d57600080fd5b50610429610d8c3660046142d1565b612896565b348015610d9d57600080fd5b50610429610dac36600461495d565b6128fd565b348015610dbd57600080fd5b506103f9610dcc3660046142f4565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b348015610e0657600080fd5b50610429610e153660046142d1565b61291f565b348015610e2657600080fd5b50610429610e35366004614c70565b612978565b348015610e4657600080fd5b50610429610e553660046143d5565b6129c5565b348015610e6657600080fd5b50610429610e753660046142d1565b612a1c565b348015610e8657600080fd5b50610429610e9536600461498f565b612a92565b348015610ea657600080fd5b50610429610eb5366004614b36565b612ec4565b348015610ec657600080fd5b50610f00610ed5366004614759565b61010e6020526000908152604090208054600182015460029092015490916001600160a01b03169083565b604080519384526001600160a01b039092166020840152908201526060016103d0565b60006001600160a01b038316610f935760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060009081526065602090815260408083206001600160a01b03949094168352929052205490565b6000610fc68261306a565b80610fd55750610fd5826130ba565b92915050565b610fe36130df565b604080518082019091526001600160a01b0392831680825291909216602090920182905261010880546001600160a01b0319908116909217905561010980549091169091179055565b61010b805461103a90615a81565b80601f016020809104026020016040519081016040528092919081815260200182805461106690615a81565b80156110b35780601f10611088576101008083540402835291602001916110b3565b820191906000526020600020905b81548152906001019060200180831161109657829003601f168201915b505050505081565b6110c36130df565b61010a546301000000900460ff16156110ef5760405163249fab5d60e01b815260040160405180910390fd5b61138861ffff82161115611116576040516306b7c75960e31b815260040160405180910390fd5b610104805461ffff909216600160d01b0261ffff60d01b19909216919091179055565b6060610101600001805461114c90615a81565b151590506111695760405180602001604052806000815250610fd5565b6101016111758361311a565b604051602001611186929190614d42565b60405160208183030381529060405292915050565b606061010160060180548060200260200160405190810160405280929190818152602001828054801561121557602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116111dc5790505b5050505050905090565b6112276130df565b60408051808201909152600080825260209091015261010880546001600160a01b031990811690915561010980549091169055565b6112646130df565b61126d81613168565b61010a5462010000900460ff16156112985760405163249fab5d60e01b815260040160405180910390fd5b60005b8251811015611321576101016006018382815181106112ca57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018101845560009384529190922060108204018054600f9092166002026101000a61ffff8181021990931692909316929092021790558061131981615ae2565b91505061129b565b505050565b60006113306131d9565b90506001600160a01b03811673271682deb8c4e0901d1a1550ad2e64d568e69909148061137957506001600160a01b0381167386b82972282dd22348374bc63fd21620f7ed847b145b8061139157506097546001600160a01b038281169116145b156113a0576113218383613200565b604051634f631ebf60e01b815260040160405180910390fd5b600082815260ca602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161142e57506040805180820190915260c9546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061144d906001600160601b031687615752565b6114579190615732565b91519350909150505b9250929050565b61146f6131d9565b6001600160a01b0316856001600160a01b03161480611495575061149585610dcc6131d9565b6114b15760405162461bcd60e51b8152600401610f8a9061534e565b6114be85858585856133b2565b5050505050565b6114cd6130df565b6114d681613168565b5061010a805465ff0000000000191665010000000000179055565b6040805160018082528183019092526000916020808301908036833701905050905060008160008151811061153657634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505061155f81611a01565b50565b61156a6130df565b61157381613168565b5061010a805467ff000000000000001916600160381b179055565b6115966130df565b61159f81613168565b61010a54610100900460ff16156115c95760405163249fab5d60e01b815260040160405180910390fd5b610100548263ffffffff1610156115f357604051638a164f6360e01b815260040160405180910390fd5b50610104805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b6116236130df565b61010480546001600160f01b0316600160f01b61ffff8416908102919091179091556116509083906135b9565b5050565b61165c6130df565b61166581613168565b61010a5462010000900460ff16156116905760405163249fab5d60e01b815260040160405180910390fd5b815161132190610107906020850190613f03565b6116ac6130df565b61010a54600160381b900460ff16156116d85760405163249fab5d60e01b815260040160405180910390fd5b82851415806116e75750828114155b15611705576040516306b7c75960e31b815260040160405180910390fd5b6000805b868110156117e757606061179f89898481811061173657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061174b91906142d1565b86868581811061176b57634e487b7160e01b600052603260045260246000fd5b9050602002013589898681811061179257634e487b7160e01b600052603260045260246000fd5b90506020020135846136b6565b8686838181106117bf57634e487b7160e01b600052603260045260246000fd5b90506020020135836117d1919061571a565b92505080806117df90615ae2565b915050611709565b506101045461010054600160a01b90910463ffffffff169061180a90839061571a565b111561182957604051638a164f6360e01b815260040160405180910390fd5b80610100600082825461183c919061571a565b909155505050505050505050565b6114be85856118576131d9565b868686612154565b606081518351146118c45760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610f8a565b600083516001600160401b038111156118ed57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611916578160200160208202803683370190505b50905060005b84518110156119b85761197d85828151811061194857634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061197057634e487b7160e01b600052603260045260246000fd5b6020026020010151610f23565b82828151811061199d57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526119b181615ae2565b905061191c565b509392505050565b6119c86130df565b61010a5460ff16156119ed5760405163249fab5d60e01b815260040160405180910390fd5b805161165090610101906020840190613fac565b73365110b34b46927b2158e07e6d3c6d4802e032f06360f0e59661010160fe60ff611a346097546001600160a01b031690565b866040518663ffffffff1660e01b8152600401611a55959493929190615476565b60006040518083038186803b158015611a6d57600080fd5b505af41580156114be573d6000803e3d6000fd5b611a896137d7565b611a936000613850565b565b61010180548190611aa590615a81565b80601f0160208091040260200160405190810160405280929190818152602001828054611ad190615a81565b8015611b1e5780601f10611af357610100808354040283529160200191611b1e565b820191906000526020600020905b815481529060010190602001808311611b0157829003601f168201915b5050505060018301546002840154600385015460408051808201825260048801805461ffff908116835260058a01805485516020808302820181019097528181529a9b6001600160a01b03998a169b988a169a5098871698600160a01b880463ffffffff1698600160c01b8904851698600160d01b8104861698600160e01b8204871698600160f01b90920490961696929590949293818601939160009084015b82821015611c02576000848152602090819020604080518082019091529084015461ffff8082168352620100009091041681830152825260019092019101611bbf565b505050508152505090508a565b611c176130df565b610104805461ffff909216600160c01b0261ffff60c01b19909216919091179055565b611c426130df565b611c4b81613168565b5061010a805461ff001916610100179055565b610108546001600160a01b0316611c8857604051631dc68aa160e11b815260040160405180910390fd5b808314611ca8576040516306b7c75960e31b815260040160405180910390fd5b6000611cb26131d9565b90506000805b85811015611e3957610109546000906001600160a01b0316611cdc5761dead611cea565b610109546001600160a01b03165b610108549091506060906001600160a01b031663f242432a86848c8c88818110611d2457634e487b7160e01b600052603260045260246000fd5b905060200201358b8b89818110611d4b57634e487b7160e01b600052603260045260246000fd5b90506020020135866040518663ffffffff1660e01b8152600401611d73959493929190614e20565b600060405180830381600087803b158015611d8d57600080fd5b505af1158015611da1573d6000803e3d6000fd5b50505050611df0858a8a86818110611dc957634e487b7160e01b600052603260045260246000fd5b9050602002013589898781811061179257634e487b7160e01b600052603260045260246000fd5b868684818110611e1057634e487b7160e01b600052603260045260246000fd5b9050602002013584611e22919061571a565b935050508080611e3190615ae2565b915050611cb8565b506101045461010054600160a01b90910463ffffffff1690611e5c90839061571a565b1115611e7b57604051638a164f6360e01b815260040160405180910390fd5b806101006000828254611e8e919061571a565b9091555050505050505050565b611ea36130df565b60408051610160810190915280611ebd6020840184614b68565b6001600160801b03168152602090810190611eda90840184614b68565b6001600160801b0316815260200160006001600160801b03168152602001826020016020810190611f0b9190614c11565b63ffffffff168152602001611f266060840160408501614c11565b63ffffffff168152602001611f416080840160608501614c11565b63ffffffff168152602001611f5c60a0840160808501614c11565b63ffffffff16815260006020820152604001611f7e60c0840160a08501614c11565b63ffffffff168152602001611f9960e0840160c085016142d1565b6001600160a01b03168152602001611fb460e084018461562e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093909452505085815260fb60209081526040918290208451858301516001600160801b03918216600160801b918316820217835593860151600183018054606089015160808a015160a08b015160c08c0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e085015160028201805461010088015161012089015193871667ffffffffffffffff1990921691909117600160201b919096160294909417600160401b600160e01b031916600160401b6001600160a01b039092169190910217909255610140840151805192935061211f9260038501929190910190613f03565b505060405183915084907fe9a0c17645ed78ccc9996259f00297ffc75e6b9d22cd605ccc9992cc8ca3f4c190600090a3505050565b8535600090815260fb6020526040902060028101546001600160201b90910463ffffffff16111561219e57600281015461219b90600160201b900463ffffffff1687615752565b95505b600060405180608001604052806121bd6097546001600160a01b031690565b6001600160a01b03168152602001866001600160a01b0316815260200188815260200161010054815250905073365110b34b46927b2158e07e6d3c6d4802e032f0633e737b11836101018b60fc60fd8a8a896040518963ffffffff1660e01b81526004016122329897969594939291906154e4565b60006040518083038186803b15801561224a57600080fd5b505af415801561225e573d6000803e3d6000fd5b505061010d5460ff161591506122db905057600061227a6138a2565b604080516060810182528b3581526001600160a01b038a811660208084019182528385018e8152600096875261010e909152939094209151825592516001820180546001600160a01b03191691909416179092555160029091015550612453565b6060600073365110b34b46927b2158e07e6d3c6d4802e032f0635ec01e4d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561232357600080fd5b505af4158015612337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235b9190614b9e565b60405163101d90c960e31b815290915073365110b34b46927b2158e07e6d3c6d4802e032f0906380ec8648906123a0906101079060038901908e908790600401614ead565b60006040518083038186803b1580156123b857600080fd5b505af41580156123cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123f491908101906145f6565b915060005b825181101561244f57606061243c8a85848151811061242857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff166001846136b6565b508061244781615ae2565b9150506123f9565b5050505b866101006000828254612466919061571a565b9091555050600182015463ffffffff600160e01b82048116600160c01b9092041610156124e4578660fc600061249a6131d9565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a60000135815260200190815260200160002060008282546124de919061571a565b90915550505b600182015463ffffffff600160e01b90910481161015612524578735600090815260fd60205260408120805489929061251e90849061571a565b90915550505b6040516329ba982960e21b815260048101839052610101602482015260fe604482015260ff60648201526001600160a01b038616608482015260a4810188905273365110b34b46927b2158e07e6d3c6d4802e032f09063a6ea60a49060c40160006040518083038186803b15801561259b57600080fd5b505af41580156125af573d6000803e3d6000fd5b505050505050505050505050565b61010c805461103a90615a81565b6116506125d66131d9565b8383613982565b6125e56130df565b42816060015163ffffffff1610156126045763ffffffff421660608201525b600083815260fb60209081526040918290208351848301516001600160801b03918216600160801b9183168202178355938501516001830180546060880151608089015160a08a015160c08b0151959096166001600160a01b03199093169290921763ffffffff9182169098029790971767ffffffffffffffff60a01b1916600160a01b9188169190910263ffffffff60c01b191617600160c01b93871693909302929092176001600160e01b0316600160e01b9186169190910217905560e084015160028201805461010087015161012088015193871667ffffffffffffffff1990921691909117600160201b919096160294909417600160401b600160e01b031916600160401b6001600160a01b039092169190910217909255610140830151805184939261211f926003850192910190613f03565b6127446130df565b61274d81613168565b5061010a805462ff0000191662010000179055565b61276a6130df565b61277381613168565b5061010a805464ff000000001916600160201b179055565b600083815260fb60205260408082209051633e09927360e21b815260048101829052610105602482015260448101859052831515606482015273365110b34b46927b2158e07e6d3c6d4802e032f09063f82649cc9060840160206040518083038186803b1580156127fb57600080fd5b505af415801561280f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128339190614b9e565b95945050505050565b6128446130df565b61284d81613168565b5061010a805463ff00000019166301000000179055565b61286c6130df565b60408051808201909152600080825260209091015261010d805468ffffffffffffffffff19169055565b7386b82972282dd22348374bc63fd21620f7ed847b6128b36131d9565b6001600160a01b0316146128da5760405163016bdfed60e71b815260040160405180910390fd5b61010480546001600160a01b0319166001600160a01b0392909216919091179055565b6129056130df565b61290e81613168565b5061010a805460ff19166001179055565b6129276130df565b61010a5465010000000000900460ff16156129555760405163249fab5d60e01b815260040160405180910390fd5b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b6129806130df565b6040805180820190915260018082526001600160401b0392909216602090910181905261010d805468ffffffffffffffffff1916610100909202919091179091179055565b6129cd6131d9565b6001600160a01b0316856001600160a01b031614806129f357506129f385610dcc6131d9565b612a0f5760405162461bcd60e51b8152600401610f8a9061534e565b6114be8585858585613a63565b612a246137d7565b6001600160a01b038116612a895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f8a565b61155f81613850565b600054610100900460ff1615808015612ab25750600054600160ff909116105b80612acc5750303b158015612acc575060005460ff166001145b612b2f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610f8a565b6000805460ff191660011790558015612b52576000805461ff0019166101001790555b8451612b669061010b906020880190613fac565b508351612b7b9061010c906020870190613fac565b50612b9460405180602001604052806000815250613b9c565b61010f80546001600160a01b03191673271682deb8c4e0901d1a1550ad2e64d568e69909179055611388612bce60e0850160c08601614b82565b61ffff161180612bf35750611388612bed610100850160e08601614b82565b61ffff16115b80612c1357506101f4612c0d610100850160e08601614b82565b61ffff16105b80612c3e5750611388612c2a6101208501856156b9565b612c38906020810190614b82565b61ffff16115b80612c6157506000612c5660408501602086016142d1565b6001600160a01b0316145b80612c7d5750612c7760c0840160a08501614b82565b61ffff16155b15612c9b576040516306b7c75960e31b815260040160405180910390fd5b60015b612cac6101208501856156b9565b612cba9060208101906155e7565b9050811015612e0757611388612cd46101208601866156b9565b612ce29060208101906155e7565b83818110612d0057634e487b7160e01b600052603260045260246000fd5b9050604002016020016020810190612d189190614b82565b61ffff161180612dd75750612d316101208501856156b9565b612d3f9060208101906155e7565b612d4a600184615771565b818110612d6757634e487b7160e01b600052603260045260246000fd5b612d7d9260206040909202019081019150614b82565b61ffff16612d8f6101208601866156b9565b612d9d9060208101906155e7565b83818110612dbb57634e487b7160e01b600052603260045260246000fd5b612dd19260206040909202019081019150614b82565b61ffff16115b15612df5576040516306b7c75960e31b815260040160405180910390fd5b80612dff81615ae2565b915050612c9e565b5082610101612e168282615c11565b905050612e21613bcc565b610103546001600160a01b031615612e5e576101035461010454612e59916001600160a01b031690600160f01b900461ffff1661161b565b612e78565b61010454612e78908390600160f01b900461ffff1661161b565b80156114be576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b612ecc6130df565b61010a54600160201b900460ff1615612ef85760405163249fab5d60e01b815260040160405180910390fd5b611388612f086020830183614b82565b61ffff161115612f2b576040516306b7c75960e31b815260040160405180910390fd5b60015b612f3b60208301836155e7565b905081101561305b57611388612f5460208401846155e7565b83818110612f7257634e487b7160e01b600052603260045260246000fd5b9050604002016020016020810190612f8a9190614b82565b61ffff16118061302b5750612fa260208301836155e7565b612fad600184615771565b818110612fca57634e487b7160e01b600052603260045260246000fd5b612fe09260206040909202019081019150614b82565b61ffff16612ff160208401846155e7565b8381811061300f57634e487b7160e01b600052603260045260246000fd5b6130259260206040909202019081019150614b82565b61ffff16115b15613049576040516306b7c75960e31b815260040160405180910390fd5b8061305381615ae2565b915050612f2e565b50806101056113218282615d9c565b60006001600160e01b03198216636cdb3d1360e11b148061309b57506001600160e01b031982166303a24d0760e21b145b80610fd557506301ffc9a760e01b6001600160e01b0319831614610fd5565b60006001600160e01b0319821663152a902d60e11b1480610fd55750610fd58261306a565b6097546001600160a01b03166130f36131d9565b6001600160a01b031614611a93576040516330cd747160e01b815260040160405180910390fd5b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061315157613156565b613134565b50819003601f19909101908152919050565b604051663337b932bb32b960c91b602082015260270160405160208183030381529060405280519060200120816040516020016131a59190614d26565b604051602081830303815290604052805190602001201461155f57604051635ee88f9760e01b815260040160405180910390fd5b600033736bc558a6dc48defa0e7022713c23d65ab26e4fa7146131fb57503390565b503290565b600082815261010e602090815260409182902082516060810184528154815260018201546001600160a01b031692810192909252600201549181018290529061325c576040516302e8145360e61b815260040160405180910390fd5b606073365110b34b46927b2158e07e6d3c6d4802e032f06380ec864861010160060160fb6000866000015181526020019081526020016000206003018560400151876000815181106132be57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518563ffffffff1660e01b81526004016132e59493929190614ead565b60006040518083038186803b1580156132fd57600080fd5b505af4158015613311573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261333991908101906145f6565b905060005b8151811015613384576060613371846020015184848151811061242857634e487b7160e01b600052603260045260246000fd5b508061337c81615ae2565b91505061333e565b50505060009182525061010e602052604081208181556001810180546001600160a01b031916905560020155565b81518351146134145760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610f8a565b6001600160a01b03841661343a5760405162461bcd60e51b8152600401610f8a9061539c565b60006134446131d9565b905060005b845181101561354b57600085828151811061347457634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008583815181106134a057634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526065835260408082206001600160a01b038e1683529093529190912054909150818110156134f15760405162461bcd60e51b8152600401610f8a906153e1565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b1682528120805484929061353090849061571a565b925050819055505050508061354490615ae2565b9050613449565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161359b9291906151eb565b60405180910390a46135b1818787878787613bfb565b505050505050565b6127106001600160601b03821611156136275760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610f8a565b6001600160a01b03821661367d5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610f8a565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760c955565b6001600160a01b0384166137165760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610f8a565b60006137206131d9565b9050600061372d85613d66565b9050600061373a85613d66565b905060008681526065602090815260408083206001600160a01b038b1684529091528120805487929061376e90849061571a565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46137ce83600089898989613dbf565b50505050505050565b6137df6131d9565b6001600160a01b03166137fa6097546001600160a01b031690565b6001600160a01b031614611a935760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f8a565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61010f5461010d546040516305d3b1d360e41b81527f8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef600482018190526101009092046001600160401b03166024820152600560448201819052622625a06064830181905260016084840152600094919290916001600160a01b031690635d3b1d309060a401602060405180830381600087803b15801561394257600080fd5b505af1158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190614b9e565b935050505090565b816001600160a01b0316836001600160a01b031614156139f65760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610f8a565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b038416613a895760405162461bcd60e51b8152600401610f8a9061539c565b6000613a936131d9565b90506000613aa085613d66565b90506000613aad85613d66565b905060008681526065602090815260408083206001600160a01b038c16845290915290205485811015613af25760405162461bcd60e51b8152600401610f8a906153e1565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290613b3190849061571a565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613b91848a8a8a8a8a613dbf565b505050505050505050565b600054610100900460ff16613bc35760405162461bcd60e51b8152600401610f8a9061542b565b61155f81613e89565b600054610100900460ff16613bf35760405162461bcd60e51b8152600401610f8a9061542b565b611a93613eb9565b6001600160a01b0384163b156135b15760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613c3f9089908990889088908890600401614dc2565b602060405180830381600087803b158015613c5957600080fd5b505af1925050508015613c89575060408051601f3d908101601f19168201909252613c8691810190614941565b60015b613d3657613c95615b50565b806308c379a01415613ccf5750613caa615b68565b80613cb55750613cd1565b8060405162461bcd60e51b8152600401610f8a9190615210565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610f8a565b6001600160e01b0319811663bc197c8160e01b146137ce5760405162461bcd60e51b8152600401610f8a90615306565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613dae57634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156135b15760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613e039089908990889088908890600401614e20565b602060405180830381600087803b158015613e1d57600080fd5b505af1925050508015613e4d575060408051601f3d908101601f19168201909252613e4a91810190614941565b60015b613e5957613c95615b50565b6001600160e01b0319811663f23a6e6160e01b146137ce5760405162461bcd60e51b8152600401610f8a90615306565b600054610100900460ff16613eb05760405162461bcd60e51b8152600401610f8a9061542b565b61155f81613ef0565b600054610100900460ff16613ee05760405162461bcd60e51b8152600401610f8a9061542b565b611a93613eeb6131d9565b613850565b8051611650906067906020840190613fac565b82805482825590600052602060002090600f01601090048101928215613f9c5791602002820160005b83821115613f6c57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302613f2c565b8015613f9a5782816101000a81549061ffff0219169055600201602081600101049283019260010302613f6c565b505b50613fa8929150614020565b5090565b828054613fb890615a81565b90600052602060002090601f016020900481019282613fda5760008555613f9c565b82601f10613ff357805160ff1916838001178555613f9c565b82800160010185558215613f9c579182015b82811115613f9c578251825591602001919060010190614005565b5b80821115613fa85760008155600101614021565b803561404081615ec0565b919050565b60008083601f840112614056578182fd5b5081356001600160401b0381111561406c578182fd5b6020830191508360208260051b850101111561146057600080fd5b600082601f830112614097578081fd5b813560206140a4826156f7565b6040516140b18282615ab6565b8381528281019150858301600585901b870184018810156140d0578586fd5b855b858110156140f75781356140e581615ec0565b845292840192908401906001016140d2565b5090979650505050505050565b600082601f830112614114578081fd5b81356020614121826156f7565b60405161412e8282615ab6565b8381528281019150858301600585901b8701840188101561414d578586fd5b855b858110156140f757813561416281615eeb565b8452928401929084019060010161414f565b600082601f830112614184578081fd5b81356020614191826156f7565b60405161419e8282615ab6565b8381528281019150858301600585901b870184018810156141bd578586fd5b855b858110156140f7578135845292840192908401906001016141bf565b8035801515811461404057600080fd5b60008083601f8401126141fc578182fd5b5081356001600160401b03811115614212578182fd5b60208301915083602082850101111561146057600080fd5b600082601f83011261423a578081fd5b81356001600160401b0381111561425357614253615b13565b60405161426a601f8301601f191660200182615ab6565b81815284602083860101111561427e578283fd5b816020850160208301379081016020019190915292915050565b6000604082840312156142a9578081fd5b50919050565b80356001600160801b038116811461404057600080fd5b803561404081615efb565b6000602082840312156142e2578081fd5b81356142ed81615ec0565b9392505050565b60008060408385031215614306578081fd5b823561431181615ec0565b9150602083013561432181615ec0565b809150509250929050565b600080600080600060a08688031215614343578081fd5b853561434e81615ec0565b9450602086013561435e81615ec0565b935060408601356001600160401b0380821115614379578283fd5b61438589838a01614174565b9450606088013591508082111561439a578283fd5b6143a689838a01614174565b935060808801359150808211156143bb578283fd5b506143c88882890161422a565b9150509295509295909350565b600080600080600060a086880312156143ec578283fd5b85356143f781615ec0565b9450602086013561440781615ec0565b9350604086013592506060860135915060808601356001600160401b0381111561442f578182fd5b6143c88882890161422a565b6000806040838503121561444d578182fd5b823561445881615ec0565b9150614466602084016141db565b90509250929050565b60008060408385031215614481578182fd5b823561448c81615ec0565b946020939093013593505050565b600080604083850312156144ac578182fd5b82356144b781615ec0565b9150602083013561432181615eeb565b600080600080600080606087890312156144df578384fd5b86356001600160401b03808211156144f5578586fd5b6145018a838b01614045565b90985096506020890135915080821115614519578586fd5b6145258a838b01614045565b9096509450604089013591508082111561453d578283fd5b5061454a89828a01614045565b979a9699509497509295939492505050565b60006020828403121561456d578081fd5b81356001600160401b03811115614582578182fd5b61458e84828501614087565b949350505050565b600080604083850312156145a8578182fd5b82356001600160401b03808211156145be578384fd5b6145ca86838701614087565b935060208501359150808211156145df578283fd5b506145ec85828601614174565b9150509250929050565b60006020808385031215614608578182fd5b82516001600160401b0381111561461d578283fd5b8301601f8101851361462d578283fd5b8051614638816156f7565b6040516146458282615ab6565b8281528481019150838501600584901b85018601891015614664578687fd5b8694505b8385101561468f57805161467b81615eeb565b835260019490940193918501918501614668565b50979650505050505050565b600080604083850312156146ad578182fd5b82356001600160401b03808211156146c3578384fd5b6146cf86838701614104565b935060208501359150808211156146e4578283fd5b506145ec8582860161422a565b60008060008060408587031215614706578182fd5b84356001600160401b038082111561471c578384fd5b61472888838901614045565b90965094506020870135915080821115614740578384fd5b5061474d87828801614045565b95989497509550505050565b60006020828403121561476a578081fd5b5035919050565b600080600060608486031215614785578081fd5b833592506020840135915060408401356001600160401b03808211156147a9578283fd5b9085019061016082880312156147bd578283fd5b6147c56156ce565b6147ce836142af565b81526147dc602084016142af565b60208201526147ed604084016142af565b60408201526147fe606084016142c6565b606082015261480f608084016142c6565b608082015261482060a084016142c6565b60a082015261483160c084016142c6565b60c082015261484260e084016142c6565b60e08201526101006148558185016142c6565b90820152610120614867848201614035565b90820152610140838101358381111561487e578586fd5b61488a8a828701614104565b8284015250508093505050509250925092565b6000806000606084860312156148b1578081fd5b833592506020840135915060408401356001600160401b038111156148d4578182fd5b840161010081870312156148e6578182fd5b809150509250925092565b600080600060608486031215614905578081fd5b833592506020840135915061491c604085016141db565b90509250925092565b600060208284031215614936578081fd5b81356142ed81615ed5565b600060208284031215614952578081fd5b81516142ed81615ed5565b60006020828403121561496e578081fd5b81356001600160401b03811115614983578182fd5b61458e8482850161422a565b600080600080608085870312156149a4578182fd5b84356001600160401b03808211156149ba578384fd5b6149c68883890161422a565b955060208701359150808211156149db578384fd5b6149e78883890161422a565b945060408701359150808211156149fc578384fd5b5085016101608188031215614a0f578283fd5b91506060850135614a1f81615ec0565b939692955090935050565b60008060008060008060a08789031215614a42578384fd5b86356001600160401b0380821115614a58578586fd5b614a648a838b01614298565b97506020890135965060408901359150614a7d82615ec0565b909450606088013590614a8f82615ec0565b90935060808801359080821115614aa4578384fd5b5061454a89828a016141eb565b600080600080600060808688031215614ac8578283fd5b85356001600160401b0380821115614ade578485fd5b614aea89838a01614298565b96506020880135955060408801359150614b0382615ec0565b90935060608701359080821115614b18578283fd5b50614b25888289016141eb565b969995985093965092949392505050565b600060208284031215614b47578081fd5b81356001600160401b03811115614b5c578182fd5b61458e84828501614298565b600060208284031215614b79578081fd5b6142ed826142af565b600060208284031215614b93578081fd5b81356142ed81615eeb565b600060208284031215614baf578081fd5b5051919050565b60008060408385031215614bc8578182fd5b8235915060208301356001600160401b03811115614be4578182fd5b6145ec85828601614174565b60008060408385031215614c02578182fd5b50508035926020909101359150565b600060208284031215614c22578081fd5b81356142ed81615efb565b60008060408385031215614c3f578182fd5b8235614c4a81615efb565b915060208301356001600160401b03811115614c64578182fd5b6145ec8582860161422a565b600060208284031215614c81578081fd5b81356001600160401b03811681146142ed578182fd5b6000815180845260208085019450808401835b83811015614cc657815187529582019590820190600101614caa565b509495945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614d12816020860160208601615971565b601f01601f19169290920160200192915050565b60008251614d38818460208701615971565b9190910192915050565b6000808454614d5081615a81565b60018281168015614d685760018114614d7957614da5565b60ff19841687528287019450614da5565b8886526020808720875b85811015614d9c5781548a820152908401908201614d83565b50505082870194505b505050508351614db9818360208801615971565b01949350505050565b6001600160a01b0386811682528516602082015260a060408201819052600090614dee90830186614c97565b8281036060840152614e008186614c97565b90508281036080840152614e148185614cfa565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090614e5a90830184614cfa565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614ea157835161ffff1683529284019291840191600101614e81565b50909695505050505050565b6000608080830187845260208281860152818854614ecf818590815260200190565b60008b81526020902094509150855b81600f8201101561501c57845461ffff8082168552601082901c8116868601526040614f1381870183858a1c1661ffff169052565b6060614f29818801848660301c1661ffff169052565b61ffff84831c841616878b015260a09150614f4e828801848660501c1661ffff169052565b60c0614f638189018587851c1661ffff169052565b60e09150614f7b828901858760701c1661ffff169052565b61ffff858c1c851616610100890152614fa06101208901858760901c1661ffff169052565b61ffff85841c851616610140890152614fc56101608901858760b01c1661ffff169052565b61ffff85821c85161661018089015250614feb6101a08801848660d01c1661ffff169052565b83901c9190911661ffff166101c08601525060f01c6101e08401526001949094019361020090920191601001614ede565b935493818110156150365761ffff85168352918301916001015b8181101561505157601085901c61ffff168352918301916001015b8181101561506a5784841c61ffff168352918301916001015b8181101561508557603085901c61ffff168352918301916001015b818110156150a057604085901c61ffff168352918301916001015b818110156150bb57605085901c61ffff168352918301916001015b818110156150d657606085901c61ffff168352918301916001015b818110156150f157607085901c61ffff168352918301916001015b8181101561510a5784861c61ffff168352918301916001015b8181101561512557609085901c61ffff168352918301916001015b818110156151405760a085901c61ffff168352918301916001015b8181101561515b5760b085901c61ffff168352918301916001015b818110156151765760c085901c61ffff168352918301916001015b818110156151915760d085901c61ffff168352918301916001015b818110156151ac5760e085901c61ffff168352918301916001015b818110156151c05760f085901c8352918301915b50506040860197909752505050506060015292915050565b6020815260006142ed6020830184614c97565b6040815260006151fe6040830185614c97565b82810360208401526128338185614c97565b6020815260006142ed6020830184614cfa565b60006101408083526152378184018e614cfa565b9050602060018060a01b03808e16828601526040818e1681870152818d16606087015263ffffffff8c16608087015261ffff9150818b1660a0870152818a1660c087015281891660e087015281881661010087015285840361012087015280840182885116855283880151828587015281815180845260608801915086830197508893505b808410156152ec5787518051871683528781015187168884015297870197600194909401939250908401906152bc565b50809750505050505050509b9a5050505050505050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060a082018783526020878185015286604085015260018060a01b03808716606086015260a0608086015282865180855260c0870191508388019450855b818110156154d35785518416835294840194918401916001016154b5565b50909b9a5050505050505050505050565b60006101408a8352896020840152806040840152883581840152506020880135601e19893603018112615515578182fd5b880180356001600160401b0381111561552c578283fd5b8060051b8036038b131561553e578384fd5b604061016086015261018085018290526101a06001600160fb1b03831115615564578485fd5b816020850182880137818601935080840192508483528a6060870152896080870152808685030160a0870152505061559d818789614cd1565b85516001600160a01b0390811660c087015260208701511660e08601526040860151610100860152606086015161012086015292506155da915050565b9998505050505050505050565b6000808335601e198436030181126155fd578283fd5b8301803591506001600160401b03821115615616578283fd5b6020019150600681901b360382131561146057600080fd5b6000808335601e19843603018112615644578283fd5b8301803591506001600160401b0382111561565d578283fd5b6020019150600581901b360382131561146057600080fd5b6000808335601e1984360301811261568b578283fd5b8301803591506001600160401b038211156156a4578283fd5b60200191503681900382131561146057600080fd5b60008235603e19833603018112614d38578182fd5b60405161016081016001600160401b03811182821017156156f1576156f1615b13565b60405290565b60006001600160401b0382111561571057615710615b13565b5060051b60200190565b6000821982111561572d5761572d615afd565b500190565b60008261574d57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561576c5761576c615afd565b500290565b60008282101561578357615783615afd565b500390565b5b818110156116505760008155600101615789565b600160401b8311156157b1576157b1615b13565b80548382558084101561580a57816000526020600020600f850160041c8101601e8660011b1680156157f4576000198083018054828460200360031b1c16815550505b50615807600f840160041c830182615788565b50505b506000818152602081208391805b868110156137ce5761584a61582c85615b36565b845461ffff600386901b81811b801990931693909116901b16178455565b602084019350600282019150601e82111561586a57600091506001830192505b600101615818565b6001600160401b0383111561588957615889615b13565b6158938154615a81565b600080601f8611601f8411818117156158b25760008681526020902092505b80156158e157601f880160051c830160208910156158cd5750825b6158df601f870160051c850182615788565b505b508060018114615915576000945087156158fc578387013594505b600188901b60001960038a901b1c198616178655615967565b601f198816945082845b8681101561593f578886013582556020958601956001909201910161591f565b508886101561595c5760001960f88a60031b161c19858901351681555b5060018860011b0186555b5050505050505050565b60005b8381101561598c578181015183820152602001615974565b8381111561599b576000848401525b50505050565b81356159ac81615eeb565b815461ffff191661ffff82161782555060018082016020840135601e198536030181126159d857600080fd5b840180356001600160401b038111156159f057600080fd5b6020820191508060061b3603821315615a0857600080fd5b600160401b811115615a1c57615a1c615b13565b825481845580821015615a51576000848152602081208381019083015b80821015615a4d5782825590870190615a39565b5050505b50600092835260208320925b818110156137ce57615a6f8385615e7c565b92840192604092909201918401615a5d565b600181811c90821680615a9557607f821691505b602082108114156142a957634e487b7160e01b600052602260045260246000fd5b601f8201601f191681016001600160401b0381118282101715615adb57615adb615b13565b6040525050565b6000600019821415615af657615af6615afd565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60008135610fd581615ec0565b60008135610fd581615eeb565b60008135610fd581615efb565b600060033d1115615b6557600481823e5160e01c5b90565b600060443d1015615b765790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615ba557505050505090565b8285019150815181811115615bbd5750505050505090565b843d8701016020828501011115615bd75750505050505090565b615be660208286010187615ab6565b509095945050505050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b615c1b8283615675565b615c26818385615872565b5050615c40615c3760208401615b29565b60018301615bf1565b615c58615c4f60408401615b29565b60028301615bf1565b60038101615c71615c6b60608501615b29565b82615bf1565b615ca4615c8060808501615b43565b82805463ffffffff60a01b191660a09290921b63ffffffff60a01b16919091179055565b615cd3615cb360a08501615b36565b82805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b615d02615ce260c08501615b36565b82805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b615d31615d1160e08501615b36565b82805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b615d65615d416101008501615b36565b8280546001600160f01b031660f09290921b6001600160f01b031916919091179055565b50615d80615d776101208401846156b9565b600483016159a1565b615d8e61014083018361562e565b61599b81836006860161579d565b8135615da781615eeb565b815461ffff191661ffff82161782555060018082016020840135601e19853603018112615dd357600080fd5b840180356001600160401b03811115615deb57600080fd5b6020820191508060061b3603821315615e0357600080fd5b600160401b811115615e1757615e17615b13565b825481845580821015615e4c576000848152602081208381019083015b80821015615e485782825590870190615e34565b5050505b50600092835260208320925b818110156137ce57615e6a8385615e7c565b92840192604092909201918401615e58565b8135615e8781615eeb565b815461ffff191661ffff8216178255506020820135615ea581615eeb565b815463ffff0000191660109190911b63ffff00001617905550565b6001600160a01b038116811461155f57600080fd5b6001600160e01b03198116811461155f57600080fd5b61ffff8116811461155f57600080fd5b63ffffffff8116811461155f57600080fdfea2646970667358221220b95ce233f6ee2c2cc7d96fe0e9d03e15d7f97eceb9ce2239883b9fecc3406a5464736f6c63430008040033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.