Overview
TokenID
46
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
EternalSundials
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "erc721a/contracts/extensions/ERC721AQueryable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/token/common/ERC2981.sol"; contract EternalSundials is ERC721AQueryable, Ownable, ReentrancyGuard, ERC2981 { using Strings for uint256; string public uriPrefix = ""; string public uriSuffix = ".json"; uint256 public cost; uint256 public maxSupply; uint256 public maxMintAmountPerTx; bool public paused = true; constructor( string memory _tokenName, string memory _tokenSymbol, uint256 _maxSupply ) ERC721A(_tokenName, _tokenSymbol) Ownable(_msgSender()) { // Set defaults at deployment cost = 10 ether; // 10 Apecoin maxSupply = _maxSupply; // Passed in constructor maxMintAmountPerTx = 10; // Default max mint per transaction // Set default royalty to 8% (800 basis points) _setDefaultRoyalty(0xE0Fb2232D81B4cD9BBFE2Ade1402C2De018a9225, 800); } modifier mintCompliance(uint256 _mintAmount) { require( _mintAmount > 0 && _mintAmount <= maxMintAmountPerTx, "Invalid mint amount!" ); require( totalSupply() + _mintAmount <= maxSupply, "Max supply exceeded!" ); _; } modifier mintPriceCompliance(uint256 _mintAmount) { require(msg.value >= cost * _mintAmount, "Insufficient funds!"); _; } function mint(uint256 _mintAmount) public payable mintCompliance(_mintAmount) mintPriceCompliance(_mintAmount) { require(!paused, "The contract is paused!"); _safeMint(_msgSender(), _mintAmount); } function mintForAddress(uint256 _mintAmount, address _receiver) public mintCompliance(_mintAmount) onlyOwner { _safeMint(_receiver, _mintAmount); } function setMaxSupply(uint256 _newMaxSupply) public onlyOwner { require(_newMaxSupply >= totalSupply(), "Cannot set maxSupply below minted tokens"); maxSupply = _newMaxSupply; } // Override _startTokenId to start token IDs at 1 instead of 0. function _startTokenId() internal view virtual override returns (uint256) { return 1; } function tokenURI(uint256 _tokenId) public view virtual override(ERC721A, IERC721A) returns (string memory) { require(_exists(_tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory currentBaseURI = _baseURI(); return bytes(currentBaseURI).length > 0 ? string(abi.encodePacked(currentBaseURI, _tokenId.toString(), uriSuffix)) : ""; } function setCost(uint256 _cost) public onlyOwner { cost = _cost; } function setMaxMintAmountPerTx(uint256 _maxMintAmountPerTx) public onlyOwner { maxMintAmountPerTx = _maxMintAmountPerTx; } function setUriPrefix(string memory _uriPrefix) public onlyOwner { uriPrefix = _uriPrefix; } function setUriSuffix(string memory _uriSuffix) public onlyOwner { uriSuffix = _uriSuffix; } function setPaused(bool _state) public onlyOwner { paused = _state; } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721A, IERC721A, ERC2981) returns (bool) { return ERC721A.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId); } function withdraw() public onlyOwner nonReentrant { (bool os, ) = payable(owner()).call{value: address(this).balance}(""); require(os, "Withdraw failed"); } function _baseURI() internal view virtual override returns (string memory) { return uriPrefix; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.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. * * The initial owner is set to the address provided by the deployer. 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 Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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 { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _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); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.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. */ interface IERC2981 is IERC165 { /** * @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. * * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers. */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol) pragma solidity ^0.8.20; import {IERC2981} from "../../interfaces/IERC2981.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.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 ERC. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. */ abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator); /** * @dev The default royalty receiver is invalid. */ error ERC2981InvalidDefaultRoyaltyReceiver(address receiver); /** * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator); /** * @dev The royalty receiver for `tokenId` is invalid. */ error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver); /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981 */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) public view virtual returns (address receiver, uint256 amount) { RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId]; address royaltyReceiver = _royaltyInfo.receiver; uint96 royaltyFraction = _royaltyInfo.royaltyFraction; if (royaltyReceiver == address(0)) { royaltyReceiver = _defaultRoyaltyInfo.receiver; royaltyFraction = _defaultRoyaltyInfo.royaltyFraction; } uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator(); return (royaltyReceiver, 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 { uint256 denominator = _feeDenominator(); if (feeNumerator > denominator) { // Royalty fee will exceed the sale price revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator); } if (receiver == address(0)) { revert ERC2981InvalidDefaultRoyaltyReceiver(address(0)); } _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 { uint256 denominator = _feeDenominator(); if (feeNumerator > denominator) { // Royalty fee will exceed the sale price revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator); } if (receiver == address(0)) { revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0)); } _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]; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 1); } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SafeCast} from "./math/SafeCast.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { using SafeCast for *; bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev The string being parsed contains characters that are not in scope of the given base. */ error StringsInvalidChar(); /** * @dev The string being parsed is not a properly formatted address. */ error StringsInvalidAddressFormat(); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString(address addr) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } /** * @dev Parse a decimal string and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input) internal pure returns (uint256) { return parseUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); uint256 result = 0; for (uint256 i = begin; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 9) return (false, 0); result *= 10; result += chr; } return (true, result); } /** * @dev Parse a decimal string and returns the value as a `int256`. * * Requirements: * - The string must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input) internal pure returns (int256) { return parseInt(input, 0, bytes(input).length); } /** * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) { (bool success, int256 value) = tryParseInt(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if * the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt(string memory input) internal pure returns (bool success, int256 value) { return _tryParseIntUncheckedBounds(input, 0, bytes(input).length); } uint256 private constant ABS_MIN_INT256 = 2 ** 255; /** * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character or if the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, int256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseIntUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseIntUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, int256 value) { bytes memory buffer = bytes(input); // Check presence of a negative sign. bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty bool positiveSign = sign == bytes1("+"); bool negativeSign = sign == bytes1("-"); uint256 offset = (positiveSign || negativeSign).toUint(); (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end); if (absSuccess && absValue < ABS_MIN_INT256) { return (true, negativeSign ? -int256(absValue) : int256(absValue)); } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) { return (true, type(int256).min); } else return (false, 0); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input) internal pure returns (uint256) { return parseHexUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseHexUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an * invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseHexUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseHexUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); // skip 0x prefix if present bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty uint256 offset = hasPrefix.toUint() * 2; uint256 result = 0; for (uint256 i = begin + offset; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 15) return (false, 0); result *= 16; unchecked { // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. result += chr; } } return (true, result); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input) internal pure returns (address) { return parseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { (bool success, address value) = tryParseAddress(input, begin, end); if (!success) revert StringsInvalidAddressFormat(); return value; } /** * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress(string memory input) internal pure returns (bool success, address value) { return tryParseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, address value) { if (end > bytes(input).length || begin > end) return (false, address(0)); bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty uint256 expectedLength = 40 + hasPrefix.toUint() * 2; // check that input is the correct length if (end - begin == expectedLength) { // length guarantees that this does not overflow, and value is at most type(uint160).max (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end); return (s, address(uint160(v))); } else { return (false, address(0)); } } function _tryParseChr(bytes1 chr) private pure returns (uint8) { uint8 value = uint8(chr); // Try to parse `chr`: // - Case 1: [0-9] // - Case 2: [a-f] // - Case 3: [A-F] // - otherwise not supported unchecked { if (value > 47 && value < 58) value -= 48; else if (value > 96 && value < 103) value -= 87; else if (value > 64 && value < 71) value -= 55; else return type(uint8).max; } return value; } /** * @dev Reads a bytes32 from a bytes array without bounds checking. * * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the * assembly block as such would prevent some optimizations. */ function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { // This is not memory safe in the general case, but all calls to this private function are within bounds. assembly ("memory-safe") { value := mload(add(buffer, add(0x20, offset))) } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * The `_sequentialUpTo()` function can be overriden to enable spot mints * (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => TokenApprovalRef) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // The amount of tokens minted above `_sequentialUpTo()`. // We call these spot mints (i.e. non-sequential mints). uint256 private _spotMinted; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID for sequential mints. * * Override this function to change the starting token ID for sequential mints. * * Note: The value returned must never change after any tokens have been minted. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the maximum token ID (inclusive) for sequential mints. * * Override this function to return a value less than 2**256 - 1, * but greater than `_startTokenId()`, to enable spot (non-sequential) mints. * * Note: The value returned must never change after any tokens have been minted. */ function _sequentialUpTo() internal view virtual returns (uint256) { return type(uint256).max; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256 result) { // Counter underflow is impossible as `_burnCounter` cannot be incremented // more than `_currentIndex + _spotMinted - _startTokenId()` times. unchecked { // With spot minting, the intermediate `result` can be temporarily negative, // and the computation must be unchecked. result = _currentIndex - _burnCounter - _startTokenId(); if (_sequentialUpTo() != type(uint256).max) result += _spotMinted; } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256 result) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { result = _currentIndex - _startTokenId(); if (_sequentialUpTo() != type(uint256).max) result += _spotMinted; } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return _burnCounter; } /** * @dev Returns the total number of tokens that are spot-minted. */ function _totalSpotMinted() internal view virtual returns (uint256) { return _spotMinted; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector); return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); _packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Returns whether the ownership slot at `index` is initialized. * An uninitialized slot does not necessarily mean that the slot has no owner. */ function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) { return _packedOwnerships[index] != 0; } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * @dev Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) { if (_startTokenId() <= tokenId) { packed = _packedOwnerships[tokenId]; if (tokenId > _sequentialUpTo()) { if (_packedOwnershipExists(packed)) return packed; _revert(OwnerQueryForNonexistentToken.selector); } // If the data at the starting slot does not exist, start the scan. if (packed == 0) { if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector); // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `tokenId` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. for (;;) { unchecked { packed = _packedOwnerships[--tokenId]; } if (packed == 0) continue; if (packed & _BITMASK_BURNED == 0) return packed; // Otherwise, the token is burned, and we must revert. // This handles the case of batch burned tokens, where only the burned bit // of the starting slot is set, and remaining slots are left uninitialized. _revert(OwnerQueryForNonexistentToken.selector); } } // Otherwise, the data exists and we can skip the scan. // This is possible because we have already achieved the target condition. // This saves 2143 gas on transfers of initialized tokens. // If the token is not burned, return `packed`. Otherwise, revert. if (packed & _BITMASK_BURNED == 0) return packed; } _revert(OwnerQueryForNonexistentToken.selector); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}. * * Requirements: * * - The caller must own the token or be an approved operator. */ function approve(address to, uint256 tokenId) public payable virtual override { _approve(to, tokenId, true); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector); return _tokenApprovals[tokenId].value; } /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) public virtual override { _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool result) { if (_startTokenId() <= tokenId) { if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]); if (tokenId < _currentIndex) { uint256 packed; while ((packed = _packedOwnerships[tokenId]) == 0) --tokenId; result = packed & _BITMASK_BURNED == 0; } } } /** * @dev Returns whether `packed` represents a token that exists. */ function _packedOwnershipExists(uint256 packed) private pure returns (bool result) { assembly { // The following is equivalent to `owner != address(0) && burned == false`. // Symbolically tested. result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED)) } } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean. from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS)); if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. from, // `from`. toMasked, // `to`. tokenId // `tokenId`. ) } if (toMasked == 0) _revert(TransferToZeroAddress.selector); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns ( bytes4 retval ) { return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { _revert(TransferToNonERC721ReceiverImplementer.selector); } assembly { revert(add(32, reason), mload(reason)) } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (quantity == 0) _revert(MintZeroQuantity.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); uint256 end = startTokenId + quantity; uint256 tokenId = startTokenId; if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector); do { assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } // The `!=` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. } while (++tokenId != end); _currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (to == address(0)) _revert(MintToZeroAddress.selector); if (quantity == 0) _revert(MintZeroQuantity.selector); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); _currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } while (index < end); // This prevents reentrancy to `_safeMint`. // It does not prevent reentrancy to `_safeMintSpot`. if (_currentIndex != end) revert(); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } /** * @dev Mints a single token at `tokenId`. * * Note: A spot-minted `tokenId` that has been burned can be re-minted again. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` must be greater than `_sequentialUpTo()`. * - `tokenId` must not exist. * * Emits a {Transfer} event for each mint. */ function _mintSpot(address to, uint256 tokenId) internal virtual { if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector); uint256 prevOwnershipPacked = _packedOwnerships[tokenId]; if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector); _beforeTokenTransfers(address(0), to, tokenId, 1); // Overflows are incredibly unrealistic. // The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1. // `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `true` (as `quantity == 1`). _packedOwnerships[tokenId] = _packOwnershipData( to, _nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked) ); // Updates: // - `balance += 1`. // - `numberMinted += 1`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1; // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } ++_spotMinted; } _afterTokenTransfers(address(0), to, tokenId, 1); } /** * @dev Safely mints a single token at `tokenId`. * * Note: A spot-minted `tokenId` that has been burned can be re-minted again. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}. * - `tokenId` must be greater than `_sequentialUpTo()`. * - `tokenId` must not exist. * * See {_mintSpot}. * * Emits a {Transfer} event. */ function _safeMintSpot( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mintSpot(to, tokenId); unchecked { if (to.code.length != 0) { uint256 currentSpotMinted = _spotMinted; if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } // This prevents reentrancy to `_safeMintSpot`. // It does not prevent reentrancy to `_safeMint`. if (_spotMinted != currentSpotMinted) revert(); } } } /** * @dev Equivalent to `_safeMintSpot(to, tokenId, '')`. */ function _safeMintSpot(address to, uint256 tokenId) internal virtual { _safeMintSpot(to, tokenId, ''); } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Equivalent to `_approve(to, tokenId, false)`. */ function _approve(address to, uint256 tokenId) internal virtual { _approve(to, tokenId, false); } /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - `tokenId` must exist. * * Emits an {Approval} event. */ function _approve( address to, uint256 tokenId, bool approvalCheck ) internal virtual { address owner = ownerOf(tokenId); if (approvalCheck && _msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { _revert(ApprovalCallerNotOwnerNorApproved.selector); } _tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times. unchecked { _burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = _packedOwnerships[index]; if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); _packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual 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) } } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721AQueryable.sol'; import '../ERC721A.sol'; /** * @title ERC721AQueryable. * * @dev ERC721A subclass with convenience query functions. */ abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable { /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory ownership) { unchecked { if (tokenId >= _startTokenId()) { if (tokenId > _sequentialUpTo()) return _ownershipAt(tokenId); if (tokenId < _nextTokenId()) { // If the `tokenId` is within bounds, // scan backwards for the initialized ownership slot. while (!_ownershipIsInitialized(tokenId)) --tokenId; return _ownershipAt(tokenId); } } } } /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] calldata tokenIds) external view virtual override returns (TokenOwnership[] memory) { TokenOwnership[] memory ownerships; uint256 i = tokenIds.length; assembly { // Grab the free memory pointer. ownerships := mload(0x40) // Store the length. mstore(ownerships, i) // Allocate one word for the length, // `tokenIds.length` words for the pointers. i := shl(5, i) // Multiply `i` by 32. mstore(0x40, add(add(ownerships, 0x20), i)) } while (i != 0) { uint256 tokenId; assembly { i := sub(i, 0x20) tokenId := calldataload(add(tokenIds.offset, i)) } TokenOwnership memory ownership = explicitOwnershipOf(tokenId); assembly { // Store the pointer of `ownership` in the `ownerships` array. mstore(add(add(ownerships, 0x20), i), ownership) } } return ownerships; } /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view virtual override returns (uint256[] memory) { return _tokensOfOwnerIn(owner, start, stop); } /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) { // If spot mints are enabled, full-range scan is disabled. if (_sequentialUpTo() != type(uint256).max) _revert(NotCompatibleWithSpotMints.selector); uint256 start = _startTokenId(); uint256 stop = _nextTokenId(); uint256[] memory tokenIds; if (start != stop) tokenIds = _tokensOfOwnerIn(owner, start, stop); return tokenIds; } /** * @dev Helper function for returning an array of token IDs owned by `owner`. * * Note that this function is optimized for smaller bytecode size over runtime gas, * since it is meant to be called off-chain. */ function _tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) private view returns (uint256[] memory tokenIds) { unchecked { if (start >= stop) _revert(InvalidQueryRange.selector); // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) start = _startTokenId(); uint256 nextTokenId = _nextTokenId(); // If spot mints are enabled, scan all the way until the specified `stop`. uint256 stopLimit = _sequentialUpTo() != type(uint256).max ? stop : nextTokenId; // Set `stop = min(stop, stopLimit)`. if (stop >= stopLimit) stop = stopLimit; // Number of tokens to scan. uint256 tokenIdsMaxLength = balanceOf(owner); // Set `tokenIdsMaxLength` to zero if the range contains no tokens. if (start >= stop) tokenIdsMaxLength = 0; // If there are one or more tokens to scan. if (tokenIdsMaxLength != 0) { // Set `tokenIdsMaxLength = min(balanceOf(owner), tokenIdsMaxLength)`. if (stop - start <= tokenIdsMaxLength) tokenIdsMaxLength = stop - start; uint256 m; // Start of available memory. assembly { // Grab the free memory pointer. tokenIds := mload(0x40) // Allocate one word for the length, and `tokenIdsMaxLength` words // for the data. `shl(5, x)` is equivalent to `mul(32, x)`. m := add(tokenIds, shl(5, add(tokenIdsMaxLength, 1))) mstore(0x40, m) } // We need to call `explicitOwnershipOf(start)`, // because the slot at `start` may not be initialized. TokenOwnership memory ownership = explicitOwnershipOf(start); address currOwnershipAddr; // If the starting slot exists (i.e. not burned), // initialize `currOwnershipAddr`. // `ownership.address` will not be zero, // as `start` is clamped to the valid token ID range. if (!ownership.burned) currOwnershipAddr = ownership.addr; uint256 tokenIdsIdx; // Use a do-while, which is slightly more efficient for this case, // as the array will at least contain one element. do { if (_sequentialUpTo() != type(uint256).max) { // Skip the remaining unused sequential slots. if (start == nextTokenId) start = _sequentialUpTo() + 1; // Reset `currOwnershipAddr`, as each spot-minted token is a batch of one. if (start > _sequentialUpTo()) currOwnershipAddr = address(0); } ownership = _ownershipAt(start); // This implicitly allocates memory. assembly { switch mload(add(ownership, 0x40)) // if `ownership.burned == false`. case 0 { // if `ownership.addr != address(0)`. // The `addr` already has it's upper 96 bits clearned, // since it is written to memory with regular Solidity. if mload(ownership) { currOwnershipAddr := mload(ownership) } // if `currOwnershipAddr == owner`. // The `shl(96, x)` is to make the comparison agnostic to any // dirty upper 96 bits in `owner`. if iszero(shl(96, xor(currOwnershipAddr, owner))) { tokenIdsIdx := add(tokenIdsIdx, 1) mstore(add(tokenIds, shl(5, tokenIdsIdx)), start) } } // Otherwise, reset `currOwnershipAddr`. // This handles the case of batch burned tokens // (burned bit of first slot set, remaining slots left uninitialized). default { currOwnershipAddr := 0 } start := add(start, 1) // Free temporary memory implicitly allocated for ownership // to avoid quadratic memory expansion costs. mstore(0x40, m) } } while (!(start == stop || tokenIdsIdx == tokenIdsMaxLength)); // Store the length of the array. assembly { mstore(tokenIds, tokenIdsIdx) } } } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721A.sol'; /** * @dev Interface of ERC721AQueryable. */ interface IERC721AQueryable is IERC721A { /** * Invalid query range (`start` >= `stop`). */ error InvalidQueryRange(); /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory); /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory); /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view returns (uint256[] memory); /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner(address owner) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); /** * `_sequentialUpTo()` must be greater than `_startTokenId()`. */ error SequentialUpToTooSmall(); /** * The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`. */ error SequentialMintExceedsLimit(); /** * Spot minting requires a `tokenId` greater than `_sequentialUpTo()`. */ error SpotMintTokenIdTooSmall(); /** * Cannot mint over a token that already exists. */ error TokenAlreadyExists(); /** * The feature is not compatible with spot mints. */ error NotCompatibleWithSpotMints(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_tokenName","type":"string"},{"internalType":"string","name":"_tokenSymbol","type":"string"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotCompatibleWithSpotMints","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"SequentialMintExceedsLimit","type":"error"},{"inputs":[],"name":"SequentialUpToTooSmall","type":"error"},{"inputs":[],"name":"SpotMintTokenIdTooSmall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"ownership","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintAmountPerTx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintForAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cost","type":"uint256"}],"name":"setCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMintAmountPerTx","type":"uint256"}],"name":"setMaxMintAmountPerTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriPrefix","type":"string"}],"name":"setUriPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriSuffix","type":"string"}],"name":"setUriSuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uriPrefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uriSuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405260405180602001604052806000815250600d90816100229190610711565b506040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250600e90816100679190610711565b506001601260006101000a81548160ff02191690831515021790555034801561008f57600080fd5b5060405161496f38038061496f83398181016040528101906100b19190610955565b6100bf61020660201b60201c565b838381600290816100d09190610711565b5080600390816100e09190610711565b506100ef61020e60201b60201c565b60008190555061010361020e60201b60201c565b61011161021760201b60201c565b101561012e5761012d63fed8210f60e01b61023f60201b60201c565b5b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036101a25760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016101999190610a21565b60405180910390fd5b6101b18161024960201b60201c565b506001600a81905550678ac7230489e80000600f8190555080601081905550600a6011819055506101fe73e0fb2232d81b4cd9bbfe2ade1402c2de018a922561032061030f60201b60201c565b505050610abd565b600033905090565b60006001905090565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b8060005260046000fd5b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600061031f6104b760201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156103845781816040517f6f483d0900000000000000000000000000000000000000000000000000000000815260040161037b929190610a94565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036103f65760006040517fb6d9900a0000000000000000000000000000000000000000000000000000000081526004016103ed9190610a21565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600b60008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b6000612710905090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061054257607f821691505b602082108103610555576105546104fb565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026105bd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610580565b6105c78683610580565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600061060e610609610604846105df565b6105e9565b6105df565b9050919050565b6000819050919050565b610628836105f3565b61063c61063482610615565b84845461058d565b825550505050565b600090565b610651610644565b61065c81848461061f565b505050565b5b8181101561068057610675600082610649565b600181019050610662565b5050565b601f8211156106c5576106968161055b565b61069f84610570565b810160208510156106ae578190505b6106c26106ba85610570565b830182610661565b50505b505050565b600082821c905092915050565b60006106e8600019846008026106ca565b1980831691505092915050565b600061070183836106d7565b9150826002028217905092915050565b61071a826104c1565b67ffffffffffffffff811115610733576107326104cc565b5b61073d825461052a565b610748828285610684565b600060209050601f83116001811461077b5760008415610769578287015190505b61077385826106f5565b8655506107db565b601f1984166107898661055b565b60005b828110156107b15784890151825560018201915060208501945060208101905061078c565b868310156107ce57848901516107ca601f8916826106d7565b8355505b6001600288020188555050505b505050505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b61081b82610801565b810181811067ffffffffffffffff8211171561083a576108396104cc565b5b80604052505050565b600061084d6107e3565b90506108598282610812565b919050565b600067ffffffffffffffff821115610879576108786104cc565b5b61088282610801565b9050602081019050919050565b60005b838110156108ad578082015181840152602081019050610892565b60008484015250505050565b60006108cc6108c78461085e565b610843565b9050828152602081018484840111156108e8576108e76107fc565b5b6108f384828561088f565b509392505050565b600082601f8301126109105761090f6107f7565b5b81516109208482602086016108b9565b91505092915050565b610932816105df565b811461093d57600080fd5b50565b60008151905061094f81610929565b92915050565b60008060006060848603121561096e5761096d6107ed565b5b600084015167ffffffffffffffff81111561098c5761098b6107f2565b5b610998868287016108fb565b935050602084015167ffffffffffffffff8111156109b9576109b86107f2565b5b6109c5868287016108fb565b92505060406109d686828701610940565b9150509250925092565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a0b826109e0565b9050919050565b610a1b81610a00565b82525050565b6000602082019050610a366000830184610a12565b92915050565b60006bffffffffffffffffffffffff82169050919050565b6000610a6f610a6a610a6584610a3c565b6105e9565b6105df565b9050919050565b610a7f81610a54565b82525050565b610a8e816105df565b82525050565b6000604082019050610aa96000830185610a76565b610ab66020830184610a85565b9392505050565b613ea380610acc6000396000f3fe60806040526004361061021a5760003560e01c80636f8b44b011610123578063a0712d68116100ab578063c87b56dd1161006f578063c87b56dd146107a1578063d5abeb01146107de578063e985e9c514610809578063efbd73f414610846578063f2fde38b1461086f5761021a565b8063a0712d68146106da578063a22cb465146106f6578063b071401b1461071f578063b88d4fde14610748578063c23dc68f146107645761021a565b80638462151c116100f25780638462151c146105df5780638da5cb5b1461061c57806394354fd01461064757806395d89b411461067257806399a2557a1461069d5761021a565b80636f8b44b01461053957806370a0823114610562578063715018a61461059f5780637ec4a659146105b65761021a565b80632a55205a116101a65780635503a0e8116101755780635503a0e81461043e5780635bbb2177146104695780635c975abb146104a657806362b99ad4146104d15780636352211e146104fc5761021a565b80632a55205a146103a45780633ccfd60b146103e257806342842e0e146103f957806344a0d68a146104155761021a565b806313faede6116101ed57806313faede6146102e057806316ba10e01461030b57806316c38b3c1461033457806318160ddd1461035d57806323b872dd146103885761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190612a25565b610898565b6040516102539190612a6d565b60405180910390f35b34801561026857600080fd5b506102716108ba565b60405161027e9190612b18565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190612b70565b61094c565b6040516102bb9190612bde565b60405180910390f35b6102de60048036038101906102d99190612c25565b6109aa565b005b3480156102ec57600080fd5b506102f56109ba565b6040516103029190612c74565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190612dc4565b6109c0565b005b34801561034057600080fd5b5061035b60048036038101906103569190612e39565b6109db565b005b34801561036957600080fd5b50610372610a00565b60405161037f9190612c74565b60405180910390f35b6103a2600480360381019061039d9190612e66565b610a4d565b005b3480156103b057600080fd5b506103cb60048036038101906103c69190612eb9565b610d0e565b6040516103d9929190612ef9565b60405180910390f35b3480156103ee57600080fd5b506103f7610e3e565b005b610413600480360381019061040e9190612e66565b610f0c565b005b34801561042157600080fd5b5061043c60048036038101906104379190612b70565b610f2c565b005b34801561044a57600080fd5b50610453610f3e565b6040516104609190612b18565b60405180910390f35b34801561047557600080fd5b50610490600480360381019061048b9190612f82565b610fcc565b60405161049d9190613132565b60405180910390f35b3480156104b257600080fd5b506104bb61102c565b6040516104c89190612a6d565b60405180910390f35b3480156104dd57600080fd5b506104e661103f565b6040516104f39190612b18565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e9190612b70565b6110cd565b6040516105309190612bde565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b9190612b70565b6110df565b005b34801561056e57600080fd5b5061058960048036038101906105849190613154565b61113b565b6040516105969190612c74565b60405180910390f35b3480156105ab57600080fd5b506105b46111d2565b005b3480156105c257600080fd5b506105dd60048036038101906105d89190612dc4565b6111e6565b005b3480156105eb57600080fd5b5061060660048036038101906106019190613154565b611201565b604051610613919061323f565b60405180910390f35b34801561062857600080fd5b5061063161127c565b60405161063e9190612bde565b60405180910390f35b34801561065357600080fd5b5061065c6112a6565b6040516106699190612c74565b60405180910390f35b34801561067e57600080fd5b506106876112ac565b6040516106949190612b18565b60405180910390f35b3480156106a957600080fd5b506106c460048036038101906106bf9190613261565b61133e565b6040516106d1919061323f565b60405180910390f35b6106f460048036038101906106ef9190612b70565b611354565b005b34801561070257600080fd5b5061071d600480360381019061071891906132b4565b6114b4565b005b34801561072b57600080fd5b5061074660048036038101906107419190612b70565b6115bf565b005b610762600480360381019061075d9190613395565b6115d1565b005b34801561077057600080fd5b5061078b60048036038101906107869190612b70565b611623565b604051610798919061346d565b60405180910390f35b3480156107ad57600080fd5b506107c860048036038101906107c39190612b70565b611698565b6040516107d59190612b18565b60405180910390f35b3480156107ea57600080fd5b506107f3611742565b6040516108009190612c74565b60405180910390f35b34801561081557600080fd5b50610830600480360381019061082b9190613488565b611748565b60405161083d9190612a6d565b60405180910390f35b34801561085257600080fd5b5061086d600480360381019061086891906134c8565b6117dc565b005b34801561087b57600080fd5b5061089660048036038101906108919190613154565b61189c565b005b60006108a382611922565b806108b357506108b2826119b4565b5b9050919050565b6060600280546108c990613537565b80601f01602080910402602001604051908101604052809291908181526020018280546108f590613537565b80156109425780601f1061091757610100808354040283529160200191610942565b820191906000526020600020905b81548152906001019060200180831161092557829003601f168201915b5050505050905090565b600061095782611a2e565b61096c5761096b63cf4700e460e01b611ada565b5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6109b682826001611ae4565b5050565b600f5481565b6109c8611c13565b80600e90816109d79190613714565b5050565b6109e3611c13565b80601260006101000a81548160ff02191690831515021790555050565b6000610a0a611c9a565b600154600054030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610a3d611ca3565b14610a4a57600854810190505b90565b6000610a5882611ccb565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610acd57610acc63a114810060e01b611ada565b5b600080610ad984611de4565b91509150610aef8187610aea611e0b565b611e13565b610b1a57610b0486610aff611e0b565b611748565b610b1957610b186359c896be60e01b611ada565b5b5b610b278686866001611e57565b8015610b3257600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815460010191905081905550610c0085610bdc888887611e5d565b7c020000000000000000000000000000000000000000000000000000000017611e85565b600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603610c865760006001850190506000600460008381526020019081526020016000205403610c84576000548114610c83578360046000838152602001908152602001600020819055505b5b505b600073ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a460008103610cf857610cf763ea553b3460e01b611ada565b5b610d058787876001611eb0565b50505050505050565b6000806000600c6000868152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a90046bffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610def57600b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600b60000160149054906101000a90046bffffffffffffffffffffffff1690505b6000610df9611eb6565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610e219190613815565b610e2b9190613886565b9050828195509550505050509250929050565b610e46611c13565b610e4e611ec0565b6000610e5861127c565b73ffffffffffffffffffffffffffffffffffffffff1647604051610e7b906138e8565b60006040518083038185875af1925050503d8060008114610eb8576040519150601f19603f3d011682016040523d82523d6000602084013e610ebd565b606091505b5050905080610f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef890613949565b60405180910390fd5b50610f0a611f06565b565b610f27838383604051806020016040528060008152506115d1565b505050565b610f34611c13565b80600f8190555050565b600e8054610f4b90613537565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7790613537565b8015610fc45780601f10610f9957610100808354040283529160200191610fc4565b820191906000526020600020905b815481529060010190602001808311610fa757829003601f168201915b505050505081565b606080600084849050905060405191508082528060051b90508060208301016040525b60008114611021576000602082039150818601359050600061101082611623565b905080836020860101525050610fef565b819250505092915050565b601260009054906101000a900460ff1681565b600d805461104c90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461107890613537565b80156110c55780601f1061109a576101008083540402835291602001916110c5565b820191906000526020600020905b8154815290600101906020018083116110a857829003601f168201915b505050505081565b60006110d882611ccb565b9050919050565b6110e7611c13565b6110ef610a00565b811015611131576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128906139db565b60405180910390fd5b8060108190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361118157611180638f4eb60460e01b611ada565b5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6111da611c13565b6111e46000611f10565b565b6111ee611c13565b80600d90816111fd9190613714565b5050565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61122c611ca3565b146112425761124163bdba09d760e01b611ada565b5b600061124c611c9a565b90506000611258611fd6565b905060608183146112715761126e858484611fdf565b90505b809350505050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60115481565b6060600380546112bb90613537565b80601f01602080910402602001604051908101604052809291908181526020018280546112e790613537565b80156113345780601f1061130957610100808354040283529160200191611334565b820191906000526020600020905b81548152906001019060200180831161131757829003601f168201915b5050505050905090565b606061134b848484611fdf565b90509392505050565b8060008111801561136757506011548111155b6113a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161139d90613a47565b60405180910390fd5b601054816113b2610a00565b6113bc9190613a67565b11156113fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f490613ae7565b60405180910390fd5b8180600f5461140c9190613815565b34101561144e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144590613b53565b60405180910390fd5b601260009054906101000a900460ff161561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590613bbf565b60405180910390fd5b6114af6114a961219b565b846121a3565b505050565b80600760006114c1611e0b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661156e611e0b565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516115b39190612a6d565b60405180910390a35050565b6115c7611c13565b8060118190555050565b6115dc848484610a4d565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461161d57611607848484846121c1565b61161c5761161b63d1a57ed660e01b611ada565b5b5b50505050565b61162b61296a565b611633611c9a565b821061169257611641611ca3565b82111561165857611651826122f0565b9050611693565b611660611fd6565b821015611691575b6116718261231b565b6116815781600190039150611668565b61168a826122f0565b9050611693565b5b5b919050565b60606116a382611a2e565b6116e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d990613c51565b60405180910390fd5b60006116ec61233b565b9050600081511161170c576040518060200160405280600081525061173a565b80611716846123cd565b600e60405160200161172a93929190613d30565b6040516020818303038152906040525b915050919050565b60105481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b816000811180156117ef57506011548111155b61182e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182590613a47565b60405180910390fd5b6010548161183a610a00565b6118449190613a67565b1115611885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187c90613ae7565b60405180910390fd5b61188d611c13565b61189782846121a3565b505050565b6118a4611c13565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119165760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161190d9190612bde565b60405180910390fd5b61191f81611f10565b50565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061197d57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806119ad5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611a275750611a268261249b565b5b9050919050565b600081611a39611c9a565b11611ad457611a46611ca3565b821115611a7057611a696004600084815260200190815260200160002054612505565b9050611ad5565b600054821015611ad35760005b6000600460008581526020019081526020016000205491508103611aac5782611aa590613d61565b9250611a7d565b60007c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b8060005260046000fd5b6000611aef836110cd565b9050818015611b3157508073ffffffffffffffffffffffffffffffffffffffff16611b18611e0b565b73ffffffffffffffffffffffffffffffffffffffff1614155b15611b5d57611b4781611b42611e0b565b611748565b611b5c57611b5b63cfb3b94260e01b611ada565b5b5b836006600085815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b611c1b61219b565b73ffffffffffffffffffffffffffffffffffffffff16611c3961127c565b73ffffffffffffffffffffffffffffffffffffffff1614611c9857611c5c61219b565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c8f9190612bde565b60405180910390fd5b565b60006001905090565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b600081611cd6611c9a565b11611dce5760046000838152602001908152602001600020549050611cf9611ca3565b821115611d1e57611d0981612505565b611ddf57611d1d63df2d9b4260e01b611ada565b5b60008103611da5576000548210611d4057611d3f63df2d9b4260e01b611ada565b5b5b60046000836001900393508381526020019081526020016000205490506000810315611da05760007c010000000000000000000000000000000000000000000000000000000082160315611ddf57611d9f63df2d9b4260e01b611ada565b5b611d41565b60007c010000000000000000000000000000000000000000000000000000000082160315611ddf575b611dde63df2d9b4260e01b611ada565b5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8611e74868684612546565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b6000612710905090565b6002600a5403611efc576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600a81905550565b6001600a81905550565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008054905090565b6060818310611ff957611ff86332c1995a60e01b611ada565b5b612001611c9a565b83101561201357612010611c9a565b92505b600061201d611fd6565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61204a611ca3565b036120555781612057565b835b9050808410612064578093505b600061206f8761113b565b905084861061207d57600090505b600081146121915780868603116120945785850390505b600060405194506001820160051b850190508060405260006120b588611623565b9050600081604001516120ca57816000015190505b60005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6120f6611ca3565b1461212557868a0361211057600161210c611ca3565b0199505b612118611ca3565b8a111561212457600091505b5b61212e8a6122f0565b9250604083015160008114612146576000925061216c565b83511561215257835192505b8b831860601b61216b576001820191508a8260051b8a01525b5b5060018a01995083604052888a148061218457508481145b156120cd57808852505050505b5050509392505050565b600033905090565b6121bd82826040518060200160405280600081525061254f565b5050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026121e7611e0b565b8786866040518563ffffffff1660e01b81526004016122099493929190613ddf565b6020604051808303816000875af192505050801561224557506040513d601f19601f820116820180604052508101906122429190613e40565b60015b61229d573d8060008114612275576040519150601f19603f3d011682016040523d82523d6000602084013e61227a565b606091505b5060008151036122955761229463d1a57ed660e01b611ada565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6122f861296a565b61231460046000848152602001908152602001600020546125cb565b9050919050565b600080600460008481526020019081526020016000205414159050919050565b6060600d805461234a90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461237690613537565b80156123c35780601f10612398576101008083540402835291602001916123c3565b820191906000526020600020905b8154815290600101906020018083116123a657829003601f168201915b5050505050905090565b6060600060016123dc84612681565b01905060008167ffffffffffffffff8111156123fb576123fa612c99565b5b6040519080825280601f01601f19166020018201604052801561242d5781602001600182028036833780820191505090505b509050600082602001820190505b600115612490578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161248457612483613857565b5b0494506000850361243b575b819350505050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60007c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b60009392505050565b61255983836127d4565b60008373ffffffffffffffffffffffffffffffffffffffff163b146125c657600080549050600083820390505b61259960008683806001019450866121c1565b6125ae576125ad63d1a57ed660e01b611ada565b5b8181106125865781600054146125c357600080fd5b50505b505050565b6125d361296a565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff168152505060007c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106126df577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816126d5576126d4613857565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061271c576d04ee2d6d415b85acef8100000000838161271257612711613857565b5b0492506020810190505b662386f26fc10000831061274b57662386f26fc10000838161274157612740613857565b5b0492506010810190505b6305f5e1008310612774576305f5e100838161276a57612769613857565b5b0492506008810190505b612710831061279957612710838161278f5761278e613857565b5b0492506004810190505b606483106127bc57606483816127b2576127b1613857565b5b0492506002810190505b600a83106127cb576001810190505b80915050919050565b600080549050600082036127f3576127f263b562e8dd60e01b611ada565b5b6128006000848385611e57565b612820836128116000866000611e5d565b61281a8561295a565b17611e85565b6004600083815260200190815260200160002081905550600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff16169050600081036128d8576128d7632e07630060e01b611ada565b5b6000838301905060008390506128ec611ca3565b600183031115612907576129066381647e3a60e01b611ada565b5b5b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a481816001019150810361290857816000819055505050506129556000848385611eb0565b505050565b60006001821460e11b9050919050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152602001600062ffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612a02816129cd565b8114612a0d57600080fd5b50565b600081359050612a1f816129f9565b92915050565b600060208284031215612a3b57612a3a6129c3565b5b6000612a4984828501612a10565b91505092915050565b60008115159050919050565b612a6781612a52565b82525050565b6000602082019050612a826000830184612a5e565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ac2578082015181840152602081019050612aa7565b60008484015250505050565b6000601f19601f8301169050919050565b6000612aea82612a88565b612af48185612a93565b9350612b04818560208601612aa4565b612b0d81612ace565b840191505092915050565b60006020820190508181036000830152612b328184612adf565b905092915050565b6000819050919050565b612b4d81612b3a565b8114612b5857600080fd5b50565b600081359050612b6a81612b44565b92915050565b600060208284031215612b8657612b856129c3565b5b6000612b9484828501612b5b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612bc882612b9d565b9050919050565b612bd881612bbd565b82525050565b6000602082019050612bf36000830184612bcf565b92915050565b612c0281612bbd565b8114612c0d57600080fd5b50565b600081359050612c1f81612bf9565b92915050565b60008060408385031215612c3c57612c3b6129c3565b5b6000612c4a85828601612c10565b9250506020612c5b85828601612b5b565b9150509250929050565b612c6e81612b3a565b82525050565b6000602082019050612c896000830184612c65565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612cd182612ace565b810181811067ffffffffffffffff82111715612cf057612cef612c99565b5b80604052505050565b6000612d036129b9565b9050612d0f8282612cc8565b919050565b600067ffffffffffffffff821115612d2f57612d2e612c99565b5b612d3882612ace565b9050602081019050919050565b82818337600083830152505050565b6000612d67612d6284612d14565b612cf9565b905082815260208101848484011115612d8357612d82612c94565b5b612d8e848285612d45565b509392505050565b600082601f830112612dab57612daa612c8f565b5b8135612dbb848260208601612d54565b91505092915050565b600060208284031215612dda57612dd96129c3565b5b600082013567ffffffffffffffff811115612df857612df76129c8565b5b612e0484828501612d96565b91505092915050565b612e1681612a52565b8114612e2157600080fd5b50565b600081359050612e3381612e0d565b92915050565b600060208284031215612e4f57612e4e6129c3565b5b6000612e5d84828501612e24565b91505092915050565b600080600060608486031215612e7f57612e7e6129c3565b5b6000612e8d86828701612c10565b9350506020612e9e86828701612c10565b9250506040612eaf86828701612b5b565b9150509250925092565b60008060408385031215612ed057612ecf6129c3565b5b6000612ede85828601612b5b565b9250506020612eef85828601612b5b565b9150509250929050565b6000604082019050612f0e6000830185612bcf565b612f1b6020830184612c65565b9392505050565b600080fd5b600080fd5b60008083601f840112612f4257612f41612c8f565b5b8235905067ffffffffffffffff811115612f5f57612f5e612f22565b5b602083019150836020820283011115612f7b57612f7a612f27565b5b9250929050565b60008060208385031215612f9957612f986129c3565b5b600083013567ffffffffffffffff811115612fb757612fb66129c8565b5b612fc385828601612f2c565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61300481612bbd565b82525050565b600067ffffffffffffffff82169050919050565b6130278161300a565b82525050565b61303681612a52565b82525050565b600062ffffff82169050919050565b6130548161303c565b82525050565b6080820160008201516130706000850182612ffb565b506020820151613083602085018261301e565b506040820151613096604085018261302d565b5060608201516130a9606085018261304b565b50505050565b60006130bb838361305a565b60808301905092915050565b6000602082019050919050565b60006130df82612fcf565b6130e98185612fda565b93506130f483612feb565b8060005b8381101561312557815161310c88826130af565b9750613117836130c7565b9250506001810190506130f8565b5085935050505092915050565b6000602082019050818103600083015261314c81846130d4565b905092915050565b60006020828403121561316a576131696129c3565b5b600061317884828501612c10565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6131b681612b3a565b82525050565b60006131c883836131ad565b60208301905092915050565b6000602082019050919050565b60006131ec82613181565b6131f6818561318c565b93506132018361319d565b8060005b8381101561323257815161321988826131bc565b9750613224836131d4565b925050600181019050613205565b5085935050505092915050565b6000602082019050818103600083015261325981846131e1565b905092915050565b60008060006060848603121561327a576132796129c3565b5b600061328886828701612c10565b935050602061329986828701612b5b565b92505060406132aa86828701612b5b565b9150509250925092565b600080604083850312156132cb576132ca6129c3565b5b60006132d985828601612c10565b92505060206132ea85828601612e24565b9150509250929050565b600067ffffffffffffffff82111561330f5761330e612c99565b5b61331882612ace565b9050602081019050919050565b6000613338613333846132f4565b612cf9565b90508281526020810184848401111561335457613353612c94565b5b61335f848285612d45565b509392505050565b600082601f83011261337c5761337b612c8f565b5b813561338c848260208601613325565b91505092915050565b600080600080608085870312156133af576133ae6129c3565b5b60006133bd87828801612c10565b94505060206133ce87828801612c10565b93505060406133df87828801612b5b565b925050606085013567ffffffffffffffff811115613400576133ff6129c8565b5b61340c87828801613367565b91505092959194509250565b60808201600082015161342e6000850182612ffb565b506020820151613441602085018261301e565b506040820151613454604085018261302d565b506060820151613467606085018261304b565b50505050565b60006080820190506134826000830184613418565b92915050565b6000806040838503121561349f5761349e6129c3565b5b60006134ad85828601612c10565b92505060206134be85828601612c10565b9150509250929050565b600080604083850312156134df576134de6129c3565b5b60006134ed85828601612b5b565b92505060206134fe85828601612c10565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061354f57607f821691505b60208210810361356257613561613508565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026135ca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261358d565b6135d4868361358d565b95508019841693508086168417925050509392505050565b6000819050919050565b600061361161360c61360784612b3a565b6135ec565b612b3a565b9050919050565b6000819050919050565b61362b836135f6565b61363f61363782613618565b84845461359a565b825550505050565b600090565b613654613647565b61365f818484613622565b505050565b5b818110156136835761367860008261364c565b600181019050613665565b5050565b601f8211156136c85761369981613568565b6136a28461357d565b810160208510156136b1578190505b6136c56136bd8561357d565b830182613664565b50505b505050565b600082821c905092915050565b60006136eb600019846008026136cd565b1980831691505092915050565b600061370483836136da565b9150826002028217905092915050565b61371d82612a88565b67ffffffffffffffff81111561373657613735612c99565b5b6137408254613537565b61374b828285613687565b600060209050601f83116001811461377e576000841561376c578287015190505b61377685826136f8565b8655506137de565b601f19841661378c86613568565b60005b828110156137b45784890151825560018201915060208501945060208101905061378f565b868310156137d157848901516137cd601f8916826136da565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061382082612b3a565b915061382b83612b3a565b925082820261383981612b3a565b915082820484148315176138505761384f6137e6565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061389182612b3a565b915061389c83612b3a565b9250826138ac576138ab613857565b5b828204905092915050565b600081905092915050565b50565b60006138d26000836138b7565b91506138dd826138c2565b600082019050919050565b60006138f3826138c5565b9150819050919050565b7f5769746864726177206661696c65640000000000000000000000000000000000600082015250565b6000613933600f83612a93565b915061393e826138fd565b602082019050919050565b6000602082019050818103600083015261396281613926565b9050919050565b7f43616e6e6f7420736574206d6178537570706c792062656c6f77206d696e746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b60006139c5602883612a93565b91506139d082613969565b604082019050919050565b600060208201905081810360008301526139f4816139b8565b9050919050565b7f496e76616c6964206d696e7420616d6f756e7421000000000000000000000000600082015250565b6000613a31601483612a93565b9150613a3c826139fb565b602082019050919050565b60006020820190508181036000830152613a6081613a24565b9050919050565b6000613a7282612b3a565b9150613a7d83612b3a565b9250828201905080821115613a9557613a946137e6565b5b92915050565b7f4d617820737570706c7920657863656564656421000000000000000000000000600082015250565b6000613ad1601483612a93565b9150613adc82613a9b565b602082019050919050565b60006020820190508181036000830152613b0081613ac4565b9050919050565b7f496e73756666696369656e742066756e64732100000000000000000000000000600082015250565b6000613b3d601383612a93565b9150613b4882613b07565b602082019050919050565b60006020820190508181036000830152613b6c81613b30565b9050919050565b7f54686520636f6e74726163742069732070617573656421000000000000000000600082015250565b6000613ba9601783612a93565b9150613bb482613b73565b602082019050919050565b60006020820190508181036000830152613bd881613b9c565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000613c3b602f83612a93565b9150613c4682613bdf565b604082019050919050565b60006020820190508181036000830152613c6a81613c2e565b9050919050565b600081905092915050565b6000613c8782612a88565b613c918185613c71565b9350613ca1818560208601612aa4565b80840191505092915050565b60008154613cba81613537565b613cc48186613c71565b94506001821660008114613cdf5760018114613cf457613d27565b60ff1983168652811515820286019350613d27565b613cfd85613568565b60005b83811015613d1f57815481890152600182019150602081019050613d00565b838801955050505b50505092915050565b6000613d3c8286613c7c565b9150613d488285613c7c565b9150613d548284613cad565b9150819050949350505050565b6000613d6c82612b3a565b915060008203613d7f57613d7e6137e6565b5b600182039050919050565b600081519050919050565b600082825260208201905092915050565b6000613db182613d8a565b613dbb8185613d95565b9350613dcb818560208601612aa4565b613dd481612ace565b840191505092915050565b6000608082019050613df46000830187612bcf565b613e016020830186612bcf565b613e0e6040830185612c65565b8181036060830152613e208184613da6565b905095945050505050565b600081519050613e3a816129f9565b92915050565b600060208284031215613e5657613e556129c3565b5b6000613e6484828501613e2b565b9150509291505056fea2646970667358221220cdd3a427bc75354e732226c42cc1dd4859a936a190695fec7921723072aefb1c64736f6c634300081c0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000f457465726e616c53756e6469616c73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024553000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061021a5760003560e01c80636f8b44b011610123578063a0712d68116100ab578063c87b56dd1161006f578063c87b56dd146107a1578063d5abeb01146107de578063e985e9c514610809578063efbd73f414610846578063f2fde38b1461086f5761021a565b8063a0712d68146106da578063a22cb465146106f6578063b071401b1461071f578063b88d4fde14610748578063c23dc68f146107645761021a565b80638462151c116100f25780638462151c146105df5780638da5cb5b1461061c57806394354fd01461064757806395d89b411461067257806399a2557a1461069d5761021a565b80636f8b44b01461053957806370a0823114610562578063715018a61461059f5780637ec4a659146105b65761021a565b80632a55205a116101a65780635503a0e8116101755780635503a0e81461043e5780635bbb2177146104695780635c975abb146104a657806362b99ad4146104d15780636352211e146104fc5761021a565b80632a55205a146103a45780633ccfd60b146103e257806342842e0e146103f957806344a0d68a146104155761021a565b806313faede6116101ed57806313faede6146102e057806316ba10e01461030b57806316c38b3c1461033457806318160ddd1461035d57806323b872dd146103885761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190612a25565b610898565b6040516102539190612a6d565b60405180910390f35b34801561026857600080fd5b506102716108ba565b60405161027e9190612b18565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190612b70565b61094c565b6040516102bb9190612bde565b60405180910390f35b6102de60048036038101906102d99190612c25565b6109aa565b005b3480156102ec57600080fd5b506102f56109ba565b6040516103029190612c74565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190612dc4565b6109c0565b005b34801561034057600080fd5b5061035b60048036038101906103569190612e39565b6109db565b005b34801561036957600080fd5b50610372610a00565b60405161037f9190612c74565b60405180910390f35b6103a2600480360381019061039d9190612e66565b610a4d565b005b3480156103b057600080fd5b506103cb60048036038101906103c69190612eb9565b610d0e565b6040516103d9929190612ef9565b60405180910390f35b3480156103ee57600080fd5b506103f7610e3e565b005b610413600480360381019061040e9190612e66565b610f0c565b005b34801561042157600080fd5b5061043c60048036038101906104379190612b70565b610f2c565b005b34801561044a57600080fd5b50610453610f3e565b6040516104609190612b18565b60405180910390f35b34801561047557600080fd5b50610490600480360381019061048b9190612f82565b610fcc565b60405161049d9190613132565b60405180910390f35b3480156104b257600080fd5b506104bb61102c565b6040516104c89190612a6d565b60405180910390f35b3480156104dd57600080fd5b506104e661103f565b6040516104f39190612b18565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e9190612b70565b6110cd565b6040516105309190612bde565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b9190612b70565b6110df565b005b34801561056e57600080fd5b5061058960048036038101906105849190613154565b61113b565b6040516105969190612c74565b60405180910390f35b3480156105ab57600080fd5b506105b46111d2565b005b3480156105c257600080fd5b506105dd60048036038101906105d89190612dc4565b6111e6565b005b3480156105eb57600080fd5b5061060660048036038101906106019190613154565b611201565b604051610613919061323f565b60405180910390f35b34801561062857600080fd5b5061063161127c565b60405161063e9190612bde565b60405180910390f35b34801561065357600080fd5b5061065c6112a6565b6040516106699190612c74565b60405180910390f35b34801561067e57600080fd5b506106876112ac565b6040516106949190612b18565b60405180910390f35b3480156106a957600080fd5b506106c460048036038101906106bf9190613261565b61133e565b6040516106d1919061323f565b60405180910390f35b6106f460048036038101906106ef9190612b70565b611354565b005b34801561070257600080fd5b5061071d600480360381019061071891906132b4565b6114b4565b005b34801561072b57600080fd5b5061074660048036038101906107419190612b70565b6115bf565b005b610762600480360381019061075d9190613395565b6115d1565b005b34801561077057600080fd5b5061078b60048036038101906107869190612b70565b611623565b604051610798919061346d565b60405180910390f35b3480156107ad57600080fd5b506107c860048036038101906107c39190612b70565b611698565b6040516107d59190612b18565b60405180910390f35b3480156107ea57600080fd5b506107f3611742565b6040516108009190612c74565b60405180910390f35b34801561081557600080fd5b50610830600480360381019061082b9190613488565b611748565b60405161083d9190612a6d565b60405180910390f35b34801561085257600080fd5b5061086d600480360381019061086891906134c8565b6117dc565b005b34801561087b57600080fd5b5061089660048036038101906108919190613154565b61189c565b005b60006108a382611922565b806108b357506108b2826119b4565b5b9050919050565b6060600280546108c990613537565b80601f01602080910402602001604051908101604052809291908181526020018280546108f590613537565b80156109425780601f1061091757610100808354040283529160200191610942565b820191906000526020600020905b81548152906001019060200180831161092557829003601f168201915b5050505050905090565b600061095782611a2e565b61096c5761096b63cf4700e460e01b611ada565b5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6109b682826001611ae4565b5050565b600f5481565b6109c8611c13565b80600e90816109d79190613714565b5050565b6109e3611c13565b80601260006101000a81548160ff02191690831515021790555050565b6000610a0a611c9a565b600154600054030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610a3d611ca3565b14610a4a57600854810190505b90565b6000610a5882611ccb565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610acd57610acc63a114810060e01b611ada565b5b600080610ad984611de4565b91509150610aef8187610aea611e0b565b611e13565b610b1a57610b0486610aff611e0b565b611748565b610b1957610b186359c896be60e01b611ada565b5b5b610b278686866001611e57565b8015610b3257600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815460010191905081905550610c0085610bdc888887611e5d565b7c020000000000000000000000000000000000000000000000000000000017611e85565b600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603610c865760006001850190506000600460008381526020019081526020016000205403610c84576000548114610c83578360046000838152602001908152602001600020819055505b5b505b600073ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a460008103610cf857610cf763ea553b3460e01b611ada565b5b610d058787876001611eb0565b50505050505050565b6000806000600c6000868152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a90046bffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610def57600b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600b60000160149054906101000a90046bffffffffffffffffffffffff1690505b6000610df9611eb6565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610e219190613815565b610e2b9190613886565b9050828195509550505050509250929050565b610e46611c13565b610e4e611ec0565b6000610e5861127c565b73ffffffffffffffffffffffffffffffffffffffff1647604051610e7b906138e8565b60006040518083038185875af1925050503d8060008114610eb8576040519150601f19603f3d011682016040523d82523d6000602084013e610ebd565b606091505b5050905080610f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef890613949565b60405180910390fd5b50610f0a611f06565b565b610f27838383604051806020016040528060008152506115d1565b505050565b610f34611c13565b80600f8190555050565b600e8054610f4b90613537565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7790613537565b8015610fc45780601f10610f9957610100808354040283529160200191610fc4565b820191906000526020600020905b815481529060010190602001808311610fa757829003601f168201915b505050505081565b606080600084849050905060405191508082528060051b90508060208301016040525b60008114611021576000602082039150818601359050600061101082611623565b905080836020860101525050610fef565b819250505092915050565b601260009054906101000a900460ff1681565b600d805461104c90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461107890613537565b80156110c55780601f1061109a576101008083540402835291602001916110c5565b820191906000526020600020905b8154815290600101906020018083116110a857829003601f168201915b505050505081565b60006110d882611ccb565b9050919050565b6110e7611c13565b6110ef610a00565b811015611131576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128906139db565b60405180910390fd5b8060108190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361118157611180638f4eb60460e01b611ada565b5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6111da611c13565b6111e46000611f10565b565b6111ee611c13565b80600d90816111fd9190613714565b5050565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61122c611ca3565b146112425761124163bdba09d760e01b611ada565b5b600061124c611c9a565b90506000611258611fd6565b905060608183146112715761126e858484611fdf565b90505b809350505050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60115481565b6060600380546112bb90613537565b80601f01602080910402602001604051908101604052809291908181526020018280546112e790613537565b80156113345780601f1061130957610100808354040283529160200191611334565b820191906000526020600020905b81548152906001019060200180831161131757829003601f168201915b5050505050905090565b606061134b848484611fdf565b90509392505050565b8060008111801561136757506011548111155b6113a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161139d90613a47565b60405180910390fd5b601054816113b2610a00565b6113bc9190613a67565b11156113fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f490613ae7565b60405180910390fd5b8180600f5461140c9190613815565b34101561144e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144590613b53565b60405180910390fd5b601260009054906101000a900460ff161561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590613bbf565b60405180910390fd5b6114af6114a961219b565b846121a3565b505050565b80600760006114c1611e0b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661156e611e0b565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516115b39190612a6d565b60405180910390a35050565b6115c7611c13565b8060118190555050565b6115dc848484610a4d565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461161d57611607848484846121c1565b61161c5761161b63d1a57ed660e01b611ada565b5b5b50505050565b61162b61296a565b611633611c9a565b821061169257611641611ca3565b82111561165857611651826122f0565b9050611693565b611660611fd6565b821015611691575b6116718261231b565b6116815781600190039150611668565b61168a826122f0565b9050611693565b5b5b919050565b60606116a382611a2e565b6116e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d990613c51565b60405180910390fd5b60006116ec61233b565b9050600081511161170c576040518060200160405280600081525061173a565b80611716846123cd565b600e60405160200161172a93929190613d30565b6040516020818303038152906040525b915050919050565b60105481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b816000811180156117ef57506011548111155b61182e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182590613a47565b60405180910390fd5b6010548161183a610a00565b6118449190613a67565b1115611885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187c90613ae7565b60405180910390fd5b61188d611c13565b61189782846121a3565b505050565b6118a4611c13565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119165760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161190d9190612bde565b60405180910390fd5b61191f81611f10565b50565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061197d57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806119ad5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611a275750611a268261249b565b5b9050919050565b600081611a39611c9a565b11611ad457611a46611ca3565b821115611a7057611a696004600084815260200190815260200160002054612505565b9050611ad5565b600054821015611ad35760005b6000600460008581526020019081526020016000205491508103611aac5782611aa590613d61565b9250611a7d565b60007c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b8060005260046000fd5b6000611aef836110cd565b9050818015611b3157508073ffffffffffffffffffffffffffffffffffffffff16611b18611e0b565b73ffffffffffffffffffffffffffffffffffffffff1614155b15611b5d57611b4781611b42611e0b565b611748565b611b5c57611b5b63cfb3b94260e01b611ada565b5b5b836006600085815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b611c1b61219b565b73ffffffffffffffffffffffffffffffffffffffff16611c3961127c565b73ffffffffffffffffffffffffffffffffffffffff1614611c9857611c5c61219b565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c8f9190612bde565b60405180910390fd5b565b60006001905090565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b600081611cd6611c9a565b11611dce5760046000838152602001908152602001600020549050611cf9611ca3565b821115611d1e57611d0981612505565b611ddf57611d1d63df2d9b4260e01b611ada565b5b60008103611da5576000548210611d4057611d3f63df2d9b4260e01b611ada565b5b5b60046000836001900393508381526020019081526020016000205490506000810315611da05760007c010000000000000000000000000000000000000000000000000000000082160315611ddf57611d9f63df2d9b4260e01b611ada565b5b611d41565b60007c010000000000000000000000000000000000000000000000000000000082160315611ddf575b611dde63df2d9b4260e01b611ada565b5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8611e74868684612546565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b6000612710905090565b6002600a5403611efc576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600a81905550565b6001600a81905550565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008054905090565b6060818310611ff957611ff86332c1995a60e01b611ada565b5b612001611c9a565b83101561201357612010611c9a565b92505b600061201d611fd6565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61204a611ca3565b036120555781612057565b835b9050808410612064578093505b600061206f8761113b565b905084861061207d57600090505b600081146121915780868603116120945785850390505b600060405194506001820160051b850190508060405260006120b588611623565b9050600081604001516120ca57816000015190505b60005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6120f6611ca3565b1461212557868a0361211057600161210c611ca3565b0199505b612118611ca3565b8a111561212457600091505b5b61212e8a6122f0565b9250604083015160008114612146576000925061216c565b83511561215257835192505b8b831860601b61216b576001820191508a8260051b8a01525b5b5060018a01995083604052888a148061218457508481145b156120cd57808852505050505b5050509392505050565b600033905090565b6121bd82826040518060200160405280600081525061254f565b5050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026121e7611e0b565b8786866040518563ffffffff1660e01b81526004016122099493929190613ddf565b6020604051808303816000875af192505050801561224557506040513d601f19601f820116820180604052508101906122429190613e40565b60015b61229d573d8060008114612275576040519150601f19603f3d011682016040523d82523d6000602084013e61227a565b606091505b5060008151036122955761229463d1a57ed660e01b611ada565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6122f861296a565b61231460046000848152602001908152602001600020546125cb565b9050919050565b600080600460008481526020019081526020016000205414159050919050565b6060600d805461234a90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461237690613537565b80156123c35780601f10612398576101008083540402835291602001916123c3565b820191906000526020600020905b8154815290600101906020018083116123a657829003601f168201915b5050505050905090565b6060600060016123dc84612681565b01905060008167ffffffffffffffff8111156123fb576123fa612c99565b5b6040519080825280601f01601f19166020018201604052801561242d5781602001600182028036833780820191505090505b509050600082602001820190505b600115612490578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161248457612483613857565b5b0494506000850361243b575b819350505050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60007c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b60009392505050565b61255983836127d4565b60008373ffffffffffffffffffffffffffffffffffffffff163b146125c657600080549050600083820390505b61259960008683806001019450866121c1565b6125ae576125ad63d1a57ed660e01b611ada565b5b8181106125865781600054146125c357600080fd5b50505b505050565b6125d361296a565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff168152505060007c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106126df577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816126d5576126d4613857565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061271c576d04ee2d6d415b85acef8100000000838161271257612711613857565b5b0492506020810190505b662386f26fc10000831061274b57662386f26fc10000838161274157612740613857565b5b0492506010810190505b6305f5e1008310612774576305f5e100838161276a57612769613857565b5b0492506008810190505b612710831061279957612710838161278f5761278e613857565b5b0492506004810190505b606483106127bc57606483816127b2576127b1613857565b5b0492506002810190505b600a83106127cb576001810190505b80915050919050565b600080549050600082036127f3576127f263b562e8dd60e01b611ada565b5b6128006000848385611e57565b612820836128116000866000611e5d565b61281a8561295a565b17611e85565b6004600083815260200190815260200160002081905550600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff16169050600081036128d8576128d7632e07630060e01b611ada565b5b6000838301905060008390506128ec611ca3565b600183031115612907576129066381647e3a60e01b611ada565b5b5b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a481816001019150810361290857816000819055505050506129556000848385611eb0565b505050565b60006001821460e11b9050919050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152602001600062ffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612a02816129cd565b8114612a0d57600080fd5b50565b600081359050612a1f816129f9565b92915050565b600060208284031215612a3b57612a3a6129c3565b5b6000612a4984828501612a10565b91505092915050565b60008115159050919050565b612a6781612a52565b82525050565b6000602082019050612a826000830184612a5e565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ac2578082015181840152602081019050612aa7565b60008484015250505050565b6000601f19601f8301169050919050565b6000612aea82612a88565b612af48185612a93565b9350612b04818560208601612aa4565b612b0d81612ace565b840191505092915050565b60006020820190508181036000830152612b328184612adf565b905092915050565b6000819050919050565b612b4d81612b3a565b8114612b5857600080fd5b50565b600081359050612b6a81612b44565b92915050565b600060208284031215612b8657612b856129c3565b5b6000612b9484828501612b5b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612bc882612b9d565b9050919050565b612bd881612bbd565b82525050565b6000602082019050612bf36000830184612bcf565b92915050565b612c0281612bbd565b8114612c0d57600080fd5b50565b600081359050612c1f81612bf9565b92915050565b60008060408385031215612c3c57612c3b6129c3565b5b6000612c4a85828601612c10565b9250506020612c5b85828601612b5b565b9150509250929050565b612c6e81612b3a565b82525050565b6000602082019050612c896000830184612c65565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612cd182612ace565b810181811067ffffffffffffffff82111715612cf057612cef612c99565b5b80604052505050565b6000612d036129b9565b9050612d0f8282612cc8565b919050565b600067ffffffffffffffff821115612d2f57612d2e612c99565b5b612d3882612ace565b9050602081019050919050565b82818337600083830152505050565b6000612d67612d6284612d14565b612cf9565b905082815260208101848484011115612d8357612d82612c94565b5b612d8e848285612d45565b509392505050565b600082601f830112612dab57612daa612c8f565b5b8135612dbb848260208601612d54565b91505092915050565b600060208284031215612dda57612dd96129c3565b5b600082013567ffffffffffffffff811115612df857612df76129c8565b5b612e0484828501612d96565b91505092915050565b612e1681612a52565b8114612e2157600080fd5b50565b600081359050612e3381612e0d565b92915050565b600060208284031215612e4f57612e4e6129c3565b5b6000612e5d84828501612e24565b91505092915050565b600080600060608486031215612e7f57612e7e6129c3565b5b6000612e8d86828701612c10565b9350506020612e9e86828701612c10565b9250506040612eaf86828701612b5b565b9150509250925092565b60008060408385031215612ed057612ecf6129c3565b5b6000612ede85828601612b5b565b9250506020612eef85828601612b5b565b9150509250929050565b6000604082019050612f0e6000830185612bcf565b612f1b6020830184612c65565b9392505050565b600080fd5b600080fd5b60008083601f840112612f4257612f41612c8f565b5b8235905067ffffffffffffffff811115612f5f57612f5e612f22565b5b602083019150836020820283011115612f7b57612f7a612f27565b5b9250929050565b60008060208385031215612f9957612f986129c3565b5b600083013567ffffffffffffffff811115612fb757612fb66129c8565b5b612fc385828601612f2c565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61300481612bbd565b82525050565b600067ffffffffffffffff82169050919050565b6130278161300a565b82525050565b61303681612a52565b82525050565b600062ffffff82169050919050565b6130548161303c565b82525050565b6080820160008201516130706000850182612ffb565b506020820151613083602085018261301e565b506040820151613096604085018261302d565b5060608201516130a9606085018261304b565b50505050565b60006130bb838361305a565b60808301905092915050565b6000602082019050919050565b60006130df82612fcf565b6130e98185612fda565b93506130f483612feb565b8060005b8381101561312557815161310c88826130af565b9750613117836130c7565b9250506001810190506130f8565b5085935050505092915050565b6000602082019050818103600083015261314c81846130d4565b905092915050565b60006020828403121561316a576131696129c3565b5b600061317884828501612c10565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6131b681612b3a565b82525050565b60006131c883836131ad565b60208301905092915050565b6000602082019050919050565b60006131ec82613181565b6131f6818561318c565b93506132018361319d565b8060005b8381101561323257815161321988826131bc565b9750613224836131d4565b925050600181019050613205565b5085935050505092915050565b6000602082019050818103600083015261325981846131e1565b905092915050565b60008060006060848603121561327a576132796129c3565b5b600061328886828701612c10565b935050602061329986828701612b5b565b92505060406132aa86828701612b5b565b9150509250925092565b600080604083850312156132cb576132ca6129c3565b5b60006132d985828601612c10565b92505060206132ea85828601612e24565b9150509250929050565b600067ffffffffffffffff82111561330f5761330e612c99565b5b61331882612ace565b9050602081019050919050565b6000613338613333846132f4565b612cf9565b90508281526020810184848401111561335457613353612c94565b5b61335f848285612d45565b509392505050565b600082601f83011261337c5761337b612c8f565b5b813561338c848260208601613325565b91505092915050565b600080600080608085870312156133af576133ae6129c3565b5b60006133bd87828801612c10565b94505060206133ce87828801612c10565b93505060406133df87828801612b5b565b925050606085013567ffffffffffffffff811115613400576133ff6129c8565b5b61340c87828801613367565b91505092959194509250565b60808201600082015161342e6000850182612ffb565b506020820151613441602085018261301e565b506040820151613454604085018261302d565b506060820151613467606085018261304b565b50505050565b60006080820190506134826000830184613418565b92915050565b6000806040838503121561349f5761349e6129c3565b5b60006134ad85828601612c10565b92505060206134be85828601612c10565b9150509250929050565b600080604083850312156134df576134de6129c3565b5b60006134ed85828601612b5b565b92505060206134fe85828601612c10565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061354f57607f821691505b60208210810361356257613561613508565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026135ca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261358d565b6135d4868361358d565b95508019841693508086168417925050509392505050565b6000819050919050565b600061361161360c61360784612b3a565b6135ec565b612b3a565b9050919050565b6000819050919050565b61362b836135f6565b61363f61363782613618565b84845461359a565b825550505050565b600090565b613654613647565b61365f818484613622565b505050565b5b818110156136835761367860008261364c565b600181019050613665565b5050565b601f8211156136c85761369981613568565b6136a28461357d565b810160208510156136b1578190505b6136c56136bd8561357d565b830182613664565b50505b505050565b600082821c905092915050565b60006136eb600019846008026136cd565b1980831691505092915050565b600061370483836136da565b9150826002028217905092915050565b61371d82612a88565b67ffffffffffffffff81111561373657613735612c99565b5b6137408254613537565b61374b828285613687565b600060209050601f83116001811461377e576000841561376c578287015190505b61377685826136f8565b8655506137de565b601f19841661378c86613568565b60005b828110156137b45784890151825560018201915060208501945060208101905061378f565b868310156137d157848901516137cd601f8916826136da565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061382082612b3a565b915061382b83612b3a565b925082820261383981612b3a565b915082820484148315176138505761384f6137e6565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061389182612b3a565b915061389c83612b3a565b9250826138ac576138ab613857565b5b828204905092915050565b600081905092915050565b50565b60006138d26000836138b7565b91506138dd826138c2565b600082019050919050565b60006138f3826138c5565b9150819050919050565b7f5769746864726177206661696c65640000000000000000000000000000000000600082015250565b6000613933600f83612a93565b915061393e826138fd565b602082019050919050565b6000602082019050818103600083015261396281613926565b9050919050565b7f43616e6e6f7420736574206d6178537570706c792062656c6f77206d696e746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b60006139c5602883612a93565b91506139d082613969565b604082019050919050565b600060208201905081810360008301526139f4816139b8565b9050919050565b7f496e76616c6964206d696e7420616d6f756e7421000000000000000000000000600082015250565b6000613a31601483612a93565b9150613a3c826139fb565b602082019050919050565b60006020820190508181036000830152613a6081613a24565b9050919050565b6000613a7282612b3a565b9150613a7d83612b3a565b9250828201905080821115613a9557613a946137e6565b5b92915050565b7f4d617820737570706c7920657863656564656421000000000000000000000000600082015250565b6000613ad1601483612a93565b9150613adc82613a9b565b602082019050919050565b60006020820190508181036000830152613b0081613ac4565b9050919050565b7f496e73756666696369656e742066756e64732100000000000000000000000000600082015250565b6000613b3d601383612a93565b9150613b4882613b07565b602082019050919050565b60006020820190508181036000830152613b6c81613b30565b9050919050565b7f54686520636f6e74726163742069732070617573656421000000000000000000600082015250565b6000613ba9601783612a93565b9150613bb482613b73565b602082019050919050565b60006020820190508181036000830152613bd881613b9c565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000613c3b602f83612a93565b9150613c4682613bdf565b604082019050919050565b60006020820190508181036000830152613c6a81613c2e565b9050919050565b600081905092915050565b6000613c8782612a88565b613c918185613c71565b9350613ca1818560208601612aa4565b80840191505092915050565b60008154613cba81613537565b613cc48186613c71565b94506001821660008114613cdf5760018114613cf457613d27565b60ff1983168652811515820286019350613d27565b613cfd85613568565b60005b83811015613d1f57815481890152600182019150602081019050613d00565b838801955050505b50505092915050565b6000613d3c8286613c7c565b9150613d488285613c7c565b9150613d548284613cad565b9150819050949350505050565b6000613d6c82612b3a565b915060008203613d7f57613d7e6137e6565b5b600182039050919050565b600081519050919050565b600082825260208201905092915050565b6000613db182613d8a565b613dbb8185613d95565b9350613dcb818560208601612aa4565b613dd481612ace565b840191505092915050565b6000608082019050613df46000830187612bcf565b613e016020830186612bcf565b613e0e6040830185612c65565b8181036060830152613e208184613da6565b905095945050505050565b600081519050613e3a816129f9565b92915050565b600060208284031215613e5657613e556129c3565b5b6000613e6484828501613e2b565b9150509291505056fea2646970667358221220cdd3a427bc75354e732226c42cc1dd4859a936a190695fec7921723072aefb1c64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000f457465726e616c53756e6469616c73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024553000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _tokenName (string): EternalSundials
Arg [1] : _tokenSymbol (string): ES
Arg [2] : _maxSupply (uint256): 10000
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [4] : 457465726e616c53756e6469616c730000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [6] : 4553000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
344:3720:12:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3499:267;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11573:98:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18636:223;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18364:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;536:19:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3302:104;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3412:81;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6890:564:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;22796:3447;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2379:657:2;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;3772:176:12;;;;;;;;;;;;;:::i;:::-;;26334:187:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2968:78:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;496:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1882:1131:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;631:25:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;462:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12934:150:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2136:197:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8570:239:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2293:101:0;;;;;;;;;;;;;:::i;:::-;;3192:104:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4039:484:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1638:85:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;591:33:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11742:102:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3387:217:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1684:253:12;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;19186:231:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3052:134:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;27102:405:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1070:659:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2512:450:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;561:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;19567:162:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1943:187:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2543:215:0;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3499:267:12;3652:4;3679:38;3705:11;3679:25;:38::i;:::-;:80;;;;3721:38;3747:11;3721:25;:38::i;:::-;3679:80;3672:87;;3499:267;;;:::o;11573:98:13:-;11627:13;11659:5;11652:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11573:98;:::o;18636:223::-;18712:7;18736:16;18744:7;18736;:16::i;:::-;18731:73;;18754:50;18762:41;;;18754:7;:50::i;:::-;18731:73;18822:15;:24;18838:7;18822:24;;;;;;;;;;;:30;;;;;;;;;;;;18815:37;;18636:223;;;:::o;18364:122::-;18452:27;18461:2;18465:7;18474:4;18452:8;:27::i;:::-;18364:122;;:::o;536:19:12:-;;;;:::o;3302:104::-;1531:13:0;:11;:13::i;:::-;3389:10:12::1;3377:9;:22;;;;;;:::i;:::-;;3302:104:::0;:::o;3412:81::-;1531:13:0;:11;:13::i;:::-;3480:6:12::1;3471;;:15;;;;;;;;;;;;;;;;;;3412:81:::0;:::o;6890:564:13:-;6951:14;7343:15;:13;:15::i;:::-;7328:12;;7312:13;;:28;:46;7303:55;;7397:17;7376;:15;:17::i;:::-;:38;7372:65;;7426:11;;7416:21;;;;7372:65;6890:564;:::o;22796:3447::-;22933:27;22963;22982:7;22963:18;:27::i;:::-;22933:57;;2943:14;23131:4;23115:22;;:41;23092:66;;23214:4;23173:45;;23189:19;23173:45;;;23169:95;;23220:44;23228:35;;;23220:7;:44::i;:::-;23169:95;23276:27;23305:23;23332:35;23359:7;23332:26;:35::i;:::-;23275:92;;;;23464:68;23489:15;23506:4;23512:19;:17;:19::i;:::-;23464:24;:68::i;:::-;23459:188;;23551:43;23568:4;23574:19;:17;:19::i;:::-;23551:16;:43::i;:::-;23546:101;;23596:51;23604:42;;;23596:7;:51::i;:::-;23546:101;23459:188;23658:43;23680:4;23686:2;23690:7;23699:1;23658:21;:43::i;:::-;23790:15;23787:157;;;23928:1;23907:19;23900:30;23787:157;24316:18;:24;24335:4;24316:24;;;;;;;;;;;;;;;;24314:26;;;;;;;;;;;;24384:18;:22;24403:2;24384:22;;;;;;;;;;;;;;;;24382:24;;;;;;;;;;;24699:143;24735:2;24783:45;24798:4;24804:2;24808:19;24783:14;:45::i;:::-;2550:8;24755:73;24699:18;:143::i;:::-;24670:17;:26;24688:7;24670:26;;;;;;;;;;;:172;;;;25010:1;2550:8;24959:19;:47;:52;24955:617;;25031:19;25063:1;25053:7;:11;25031:33;;25218:1;25184:17;:30;25202:11;25184:30;;;;;;;;;;;;:35;25180:378;;25320:13;;25305:11;:28;25301:239;;25498:19;25465:17;:30;25483:11;25465:30;;;;;;;;;;;:52;;;;25301:239;25180:378;25013:559;24955:617;25681:16;2943:14;25716:2;25700:20;;:39;25681:58;;26071:7;26036:8;26003:4;25946:25;25892:1;25836;25814:292;26141:1;26129:8;:13;26125:58;;26144:39;26152:30;;;26144:7;:39::i;:::-;26125:58;26194:42;26215:4;26221:2;26225:7;26234:1;26194:20;:42::i;:::-;22923:3320;;;;22796:3447;;;:::o;2379:657:2:-;2487:16;2505:14;2531:32;2566:17;:26;2584:7;2566:26;;;;;;;;;;;2531:61;;2602:23;2628:12;:21;;;;;;;;;;;;2602:47;;2659:22;2684:12;:28;;;;;;;;;;;;2659:53;;2754:1;2727:29;;:15;:29;;;2723:173;;2790:19;:28;;;;;;;;;;;;2772:46;;2850:19;:35;;;;;;;;;;;;2832:53;;2723:173;2906:21;2962:17;:15;:17::i;:::-;2930:49;;2943:15;2931:27;;:9;:27;;;;:::i;:::-;2930:49;;;;:::i;:::-;2906:73;;2998:15;3015:13;2990:39;;;;;;;;2379:657;;;;;:::o;3772:176:12:-;1531:13:0;:11;:13::i;:::-;2500:21:5::1;:19;:21::i;:::-;3833:7:12::2;3854;:5;:7::i;:::-;3846:21;;3875;3846:55;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3832:69;;;3919:2;3911:30;;;;;;;;;;;;:::i;:::-;;;;;;;;;3822:126;2542:20:5::1;:18;:20::i;:::-;3772:176:12:o:0;26334:187:13:-;26475:39;26492:4;26498:2;26502:7;26475:39;;;;;;;;;;;;:16;:39::i;:::-;26334:187;;;:::o;2968:78:12:-;1531:13:0;:11;:13::i;:::-;3034:5:12::1;3027:4;:12;;;;2968:78:::0;:::o;496:33::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1882:1131:15:-;2021:23;2060:34;2104:9;2116:8;;:15;;2104:27;;2229:4;2223:11;2209:25;;2299:1;2287:10;2280:21;2432:1;2429;2425:9;2420:14;;2510:1;2503:4;2491:10;2487:21;2483:29;2477:4;2470:43;2532:448;2544:1;2539;:6;2532:448;;2561:15;2629:4;2626:1;2622:12;2617:17;;2696:1;2679:15;2675:23;2662:37;2651:48;;2726:31;2760:28;2780:7;2760:19;:28::i;:::-;2726:62;;2946:9;2942:1;2935:4;2923:10;2919:21;2915:29;2908:48;2811:159;;2532:448;;;2996:10;2989:17;;;;1882:1131;;;;:::o;631:25:12:-;;;;;;;;;;;;;:::o;462:28::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;12934:150:13:-;13006:7;13048:27;13067:7;13048:18;:27::i;:::-;13025:52;;12934:150;;;:::o;2136:197:12:-;1531:13:0;:11;:13::i;:::-;2233::12::1;:11;:13::i;:::-;2216;:30;;2208:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;2313:13;2301:9;:25;;;;2136:197:::0;:::o;8570:239:13:-;8642:7;8682:1;8665:19;;:5;:19;;;8661:69;;8686:44;8694:35;;;8686:7;:44::i;:::-;8661:69;1518:13;8747:18;:25;8766:5;8747:25;;;;;;;;;;;;;;;;:55;8740:62;;8570:239;;;:::o;2293:101:0:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;3192:104:12:-;1531:13:0;:11;:13::i;:::-;3279:10:12::1;3267:9;:22;;;;;;:::i;:::-;;3192:104:::0;:::o;4039:484:15:-;4117:16;4237:17;4216;:15;:17::i;:::-;:38;4212:88;;4256:44;4264:35;;;4256:7;:44::i;:::-;4212:88;4310:13;4326:15;:13;:15::i;:::-;4310:31;;4351:12;4366:14;:12;:14::i;:::-;4351:29;;4390:25;4438:4;4429:5;:13;4425:66;;4455:36;4472:5;4479;4486:4;4455:16;:36::i;:::-;4444:47;;4425:66;4508:8;4501:15;;;;;4039:484;;;:::o;1638:85:0:-;1684:7;1710:6;;;;;;;;;;;1703:13;;1638:85;:::o;591:33:12:-;;;;:::o;11742:102:13:-;11798:13;11830:7;11823:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11742:102;:::o;3387:217:15:-;3526:16;3561:36;3578:5;3585;3592:4;3561:16;:36::i;:::-;3554:43;;3387:217;;;;;:::o;1684:253:12:-;1773:11;1312:1;1298:11;:15;:52;;;;;1332:18;;1317:11;:33;;1298:52;1277:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;1458:9;;1443:11;1427:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1406:107;;;;;;;;;;;;:::i;:::-;;;;;;;;;1814:11:::1;1625;1618:4;;:18;;;;:::i;:::-;1605:9;:31;;1597:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;1850:6:::2;;;;;;;;;;;1849:7;1841:43;;;;;;;;;;;;:::i;:::-;;;;;;;;;1894:36;1904:12;:10;:12::i;:::-;1918:11;1894:9;:36::i;:::-;1523:1:::1;1684:253:::0;;:::o;19186:231:13:-;19332:8;19280:18;:39;19299:19;:17;:19::i;:::-;19280:39;;;;;;;;;;;;;;;:49;19320:8;19280:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;19391:8;19355:55;;19370:19;:17;:19::i;:::-;19355:55;;;19401:8;19355:55;;;;;;:::i;:::-;;;;;;;;19186:231;;:::o;3052:134:12:-;1531:13:0;:11;:13::i;:::-;3160:19:12::1;3139:18;:40;;;;3052:134:::0;:::o;27102:405:13:-;27271:31;27284:4;27290:2;27294:7;27271:12;:31::i;:::-;27334:1;27316:2;:14;;;:19;27312:189;;27354:56;27385:4;27391:2;27395:7;27404:5;27354:30;:56::i;:::-;27349:152;;27430:56;27438:47;;;27430:7;:56::i;:::-;27349:152;27312:189;27102:405;;;;:::o;1070:659:15:-;1194:31;;:::i;:::-;1280:15;:13;:15::i;:::-;1269:7;:26;1265:448;;1329:17;:15;:17::i;:::-;1319:7;:27;1315:61;;;1355:21;1368:7;1355:12;:21::i;:::-;1348:28;;;;1315:61;1409:14;:12;:14::i;:::-;1399:7;:24;1395:304;;;1579:51;1587:32;1611:7;1587:23;:32::i;:::-;1579:51;;1621:9;;;;;;1579:51;;;1659:21;1672:7;1659:12;:21::i;:::-;1652:28;;;;1395:304;1265:448;1070:659;;;;:::o;2512:450:12:-;2645:13;2682:17;2690:8;2682:7;:17::i;:::-;2674:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;2761:28;2792:10;:8;:10::i;:::-;2761:41;;2850:1;2825:14;2819:28;:32;:136;;;;;;;;;;;;;;;;;2890:14;2906:19;:8;:17;:19::i;:::-;2927:9;2873:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2819:136;2812:143;;;2512:450;;;:::o;561:24::-;;;;:::o;19567:162:13:-;19664:4;19687:18;:25;19706:5;19687:25;;;;;;;;;;;;;;;:35;19713:8;19687:35;;;;;;;;;;;;;;;;;;;;;;;;;19680:42;;19567:162;;;;:::o;1943:187:12:-;2045:11;1312:1;1298:11;:15;:52;;;;;1332:18;;1317:11;:33;;1298:52;1277:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;1458:9;;1443:11;1427:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1406:107;;;;;;;;;;;;:::i;:::-;;;;;;;;;1531:13:0::1;:11;:13::i;:::-;2090:33:12::2;2100:9;2111:11;2090:9;:33::i;:::-;1943:187:::0;;;:::o;2543:215:0:-;1531:13;:11;:13::i;:::-;2647:1:::1;2627:22;;:8;:22;;::::0;2623:91:::1;;2700:1;2672:31;;;;;;;;;;;:::i;:::-;;;;;;;;2623:91;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;10689:630:13:-;10774:4;11107:10;11092:25;;:11;:25;;;;:101;;;;11183:10;11168:25;;:11;:25;;;;11092:101;:177;;;;11259:10;11244:25;;:11;:25;;;;11092:177;11073:196;;10689:630;;;:::o;2116:213:2:-;2218:4;2256:26;2241:41;;;:11;:41;;;;:81;;;;2286:36;2310:11;2286:23;:36::i;:::-;2241:81;2234:88;;2116:213;;;:::o;19978:465:13:-;20043:11;20089:7;20070:15;:13;:15::i;:::-;:26;20066:371;;20126:17;:15;:17::i;:::-;20116:7;:27;20112:90;;;20152:50;20175:17;:26;20193:7;20175:26;;;;;;;;;;;;20152:22;:50::i;:::-;20145:57;;;;20112:90;20231:13;;20221:7;:23;20217:210;;;20264:14;20296:60;20344:1;20313:17;:26;20331:7;20313:26;;;;;;;;;;;;20304:35;;;20303:42;20296:60;;20347:9;;;;:::i;:::-;;;20296:60;;;20411:1;2276:8;20383:6;:24;:29;20374:38;;20246:181;20217:210;20066:371;19978:465;;;;:::o;49703:160::-;49802:13;49796:4;49789:27;49842:4;49836;49829:18;41333:460;41457:13;41473:16;41481:7;41473;:16::i;:::-;41457:32;;41504:13;:45;;;;;41544:5;41521:28;;:19;:17;:19::i;:::-;:28;;;;41504:45;41500:198;;;41568:44;41585:5;41592:19;:17;:19::i;:::-;41568:16;:44::i;:::-;41563:135;;41632:51;41640:42;;;41632:7;:51::i;:::-;41563:135;41500:198;41741:2;41708:15;:24;41724:7;41708:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;41778:7;41774:2;41758:28;;41767:5;41758:28;;;;;;;;;;;;41447:346;41333:460;;;:::o;1796:162:0:-;1866:12;:10;:12::i;:::-;1855:23;;:7;:5;:7::i;:::-;:23;;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;;;;;;;;;;:::i;:::-;;;;;;;;1851:101;1796:162::o;2407:99:12:-;2472:7;2498:1;2491:8;;2407:99;:::o;6404:108:13:-;6462:7;6488:17;6481:24;;6404:108;:::o;14380:2173::-;14447:14;14496:7;14477:15;:13;:15::i;:::-;:26;14473:2017;;14528:17;:26;14546:7;14528:26;;;;;;;;;;;;14519:35;;14583:17;:15;:17::i;:::-;14573:7;:27;14569:180;;;14624:30;14647:6;14624:22;:30::i;:::-;14656:13;14620:49;14687:47;14695:38;;;14687:7;:47::i;:::-;14569:180;14857:1;14847:6;:11;14843:1270;;14893:13;;14882:7;:24;14878:77;;14908:47;14916:38;;;14908:7;:47::i;:::-;14878:77;15502:597;15578:17;:28;15596:9;;;;;;;15578:28;;;;;;;;;;;;15569:37;;15664:1;15654:6;:11;15650:25;15667:8;15650:25;15729:1;2276:8;15701:6;:24;:29;15697:48;15732:13;15697:48;16033:47;16041:38;;;16033:7;:47::i;:::-;15502:597;;;14843:1270;16463:1;2276:8;16435:6;:24;:29;16431:48;16466:13;16431:48;14473:2017;16499:47;16507:38;;;16499:7;:47::i;:::-;14380:2173;;;;:::o;21721:474::-;21820:27;21849:23;21888:38;21929:15;:24;21945:7;21929:24;;;;;;;;;;;21888:65;;22103:18;22080:41;;22159:19;22153:26;22134:45;;22066:123;21721:474;;;:::o;47733:103::-;47793:7;47819:10;47812:17;;47733:103;:::o;20967:646::-;21112:11;21274:16;21267:5;21263:28;21254:37;;21432:16;21421:9;21417:32;21404:45;;21580:15;21569:9;21566:30;21558:5;21547:9;21544:20;21541:56;21531:66;;20967:646;;;;;:::o;28151:154::-;;;;;:::o;47060:304::-;47191:7;47210:16;2671:3;47236:19;:41;;47210:68;;2671:3;47303:31;47314:4;47320:2;47324:9;47303:10;:31::i;:::-;47295:40;;:62;;47288:69;;;47060:304;;;;;:::o;17086:443::-;17166:14;17331:16;17324:5;17320:28;17311:37;;17506:5;17492:11;17467:23;17463:41;17460:52;17453:5;17450:63;17440:73;;17086:443;;;;:::o;28952:153::-;;;;;:::o;3311:95:2:-;3369:6;3394:5;3387:12;;3311:95;:::o;2575:307:5:-;1899:1;2702:7;;:18;2698:86;;2743:30;;;;;;;;;;;;;;2698:86;1899:1;2858:7;:17;;;;2575:307::o;2888:208::-;1857:1;3068:7;:21;;;;2888:208::o;2912:187:0:-;2985:16;3004:6;;;;;;;;;;;2985:25;;3029:8;3020:6;;:17;;;;;;;;;;;;;;;;;;3083:8;3052:40;;3073:8;3052:40;;;;;;;;;;;;2975:124;2912:187;:::o;6586:101:13:-;6641:7;6667:13;;6660:20;;6586:101;:::o;4771:4906:15:-;4893:25;4967:4;4958:5;:13;4954:54;;4973:35;4981:26;;;4973:7;:35::i;:::-;4954:54;5092:15;:13;:15::i;:::-;5084:5;:23;5080:52;;;5117:15;:13;:15::i;:::-;5109:23;;5080:52;5146:19;5168:14;:12;:14::i;:::-;5146:36;;5283:17;5324;5303;:15;:17::i;:::-;:38;:59;;5351:11;5303:59;;;5344:4;5303:59;5283:79;;5438:9;5430:4;:17;5426:39;;5456:9;5449:16;;5426:39;5520:25;5548:16;5558:5;5548:9;:16::i;:::-;5520:44;;5671:4;5662:5;:13;5658:40;;5697:1;5677:21;;5658:40;5793:1;5772:17;:22;5768:3893;;5921:17;5912:5;5905:4;:12;:33;5901:71;;5967:5;5960:4;:12;5940:32;;5901:71;5990:9;6149:4;6143:11;6131:23;;6391:1;6372:17;6368:25;6365:1;6361:33;6351:8;6347:48;6342:53;;6429:1;6423:4;6416:15;6602:31;6636:26;6656:5;6636:19;:26::i;:::-;6602:60;;6680:25;6972:9;:16;;;6967:57;;7010:9;:14;;;6990:34;;6967:57;7042:19;7229:2273;7279:17;7258;:15;:17::i;:::-;:38;7254:405;;7408:11;7399:5;:20;7395:55;;7449:1;7429:17;:15;:17::i;:::-;:21;7421:29;;7395:55;7587:17;:15;:17::i;:::-;7579:5;:25;7575:61;;;7634:1;7606:30;;7575:61;7254:405;7692:19;7705:5;7692:12;:19::i;:::-;7680:31;;7833:4;7822:9;7818:20;7812:27;7928:1;7923:893;;;;9132:1;9111:22;;7805:1354;;7923:893;8202:9;8196:16;8193:121;;;8274:9;8268:16;8247:37;;8193:121;8601:5;8582:17;8578:29;8574:2;8570:38;8560:230;;8676:1;8663:11;8659:19;8644:34;;8754:5;8739:11;8736:1;8732:19;8722:8;8718:34;8711:49;8560:230;7805:1354;;9204:1;9197:5;9193:13;9184:22;;9398:1;9392:4;9385:15;9459:4;9450:5;:13;:49;;;;9482:17;9467:11;:32;9450:49;9448:52;7229:2273;;9617:11;9607:8;9600:29;9578:69;;;;5768:3893;4930:4741;;;4771:4906;;;;;:::o;656:96:3:-;709:7;735:10;728:17;;656:96;:::o;36661:110:13:-;36737:27;36747:2;36751:8;36737:27;;;;;;;;;;;;:9;:27::i;:::-;36661:110;;:::o;29533:673::-;29691:4;29736:2;29711:45;;;29757:19;:17;:19::i;:::-;29778:4;29784:7;29793:5;29711:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;29707:493;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30006:1;29989:6;:13;:18;29985:113;;30027:56;30035:47;;;30027:7;:56::i;:::-;29985:113;30168:6;30162:13;30153:6;30149:2;30145:15;30138:38;29707:493;29877:54;;;29867:64;;;:6;:64;;;;29860:71;;;29533:673;;;;;;:::o;13522:159::-;13590:21;;:::i;:::-;13630:44;13649:17;:24;13667:5;13649:24;;;;;;;;;;;;13630:18;:44::i;:::-;13623:51;;13522:159;;;:::o;13860:138::-;13939:4;13990:1;13962:17;:24;13980:5;13962:24;;;;;;;;;;;;:29;;13955:36;;13860:138;;;:::o;3954:108:12:-;4014:13;4046:9;4039:16;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3954:108;:::o;987:632:6:-;1043:13;1092:14;1129:1;1109:17;1120:5;1109:10;:17::i;:::-;:21;1092:38;;1144:20;1178:6;1167:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1144:41;;1199:11;1294:6;1290:2;1286:15;1278:6;1274:28;1267:35;;1329:247;1336:4;1329:247;;;1360:5;;;;;;;;1464:10;1459:2;1452:5;1448:14;1443:32;1438:3;1430:46;1520:2;1511:11;;;;;;:::i;:::-;;;;;1553:1;1544:5;:10;1329:247;1540:21;1329:247;1596:6;1589:13;;;;;987:632;;;:::o;763:146:7:-;839:4;877:25;862:40;;;:11;:40;;;;855:47;;763:146;;;:::o;20534:329:13:-;20604:11;20830:15;20822:6;20818:28;20799:16;20791:6;20787:29;20784:63;20774:73;;20534:329;;;:::o;46771:143::-;46904:6;46771:143;;;;;:::o;35816:766::-;35942:19;35948:2;35952:8;35942:5;:19::i;:::-;36018:1;36000:2;:14;;;:19;35996:570;;36039:11;36053:13;;36039:27;;36084:13;36106:8;36100:3;:14;36084:30;;36132:238;36162:62;36201:1;36205:2;36209:7;;;;;;36218:5;36162:30;:62::i;:::-;36157:174;;36252:56;36260:47;;;36252:7;:56::i;:::-;36157:174;36365:3;36357:5;:11;36132:238;;36538:3;36521:13;;:20;36517:34;;36543:8;;;36517:34;36021:545;;35996:570;35816:766;;;:::o;16647:361::-;16713:31;;:::i;:::-;16789:6;16756:9;:14;;:41;;;;;;;;;;;2162:3;16841:6;:33;;16807:9;:24;;:68;;;;;;;;;;;16932:1;2276:8;16904:6;:24;:29;;16885:9;:16;;:48;;;;;;;;;;;2671:3;16972:6;:28;;16943:9;:19;;:58;;;;;;;;;;;16647:361;;;:::o;25316:916:9:-;25369:7;25388:14;25405:1;25388:18;;25453:8;25444:5;:17;25440:103;;25490:8;25481:17;;;;;;:::i;:::-;;;;;25526:2;25516:12;;;;25440:103;25569:8;25560:5;:17;25556:103;;25606:8;25597:17;;;;;;:::i;:::-;;;;;25642:2;25632:12;;;;25556:103;25685:8;25676:5;:17;25672:103;;25722:8;25713:17;;;;;;:::i;:::-;;;;;25758:2;25748:12;;;;25672:103;25801:7;25792:5;:16;25788:100;;25837:7;25828:16;;;;;;:::i;:::-;;;;;25872:1;25862:11;;;;25788:100;25914:7;25905:5;:16;25901:100;;25950:7;25941:16;;;;;;:::i;:::-;;;;;25985:1;25975:11;;;;25901:100;26027:7;26018:5;:16;26014:100;;26063:7;26054:16;;;;;;:::i;:::-;;;;;26098:1;26088:11;;;;26014:100;26140:7;26131:5;:16;26127:66;;26177:1;26167:11;;;;26127:66;26219:6;26212:13;;;25316:916;;;:::o;30652:2343:13:-;30724:20;30747:13;;30724:36;;30786:1;30774:8;:13;30770:53;;30789:34;30797:25;;;30789:7;:34::i;:::-;30770:53;30834:61;30864:1;30868:2;30872:12;30886:8;30834:21;:61::i;:::-;31357:136;31393:2;31446:33;31469:1;31473:2;31477:1;31446:14;:33::i;:::-;31413:30;31434:8;31413:20;:30::i;:::-;:66;31357:18;:136::i;:::-;31323:17;:31;31341:12;31323:31;;;;;;;;;;;:170;;;;31773:1;1653:2;31743:1;:26;;31742:32;31730:8;:45;31704:18;:22;31723:2;31704:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;31883:16;2943:14;31918:2;31902:20;;:39;31883:58;;31972:1;31960:8;:13;31956:54;;31975:35;31983:26;;;31975:7;:35::i;:::-;31956:54;32025:11;32054:8;32039:12;:23;32025:37;;32076:15;32094:12;32076:30;;32135:17;:15;:17::i;:::-;32131:1;32125:3;:7;:27;32121:77;;;32154:44;32162:35;;;32154:7;:44::i;:::-;32121:77;32213:662;32623:7;32580:8;32536:1;32471:25;32409:1;32345;32315:351;32870:3;32857:9;;;;;;:16;32213:662;;32905:3;32889:13;:19;;;;31078:1841;;;32928:60;32957:1;32961:2;32965:12;32979:8;32928:20;:60::i;:::-;30714:2281;30652:2343;;:::o;17626:318::-;17696:14;17925:1;17915:8;17912:15;17886:24;17882:46;17872:56;;17626:318;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:17:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:248::-;1880:1;1890:113;1904:6;1901:1;1898:13;1890:113;;;1989:1;1984:3;1980:11;1974:18;1970:1;1965:3;1961:11;1954:39;1926:2;1923:1;1919:10;1914:15;;1890:113;;;2037:1;2028:6;2023:3;2019:16;2012:27;1860:186;1798:248;;;:::o;2052:102::-;2093:6;2144:2;2140:7;2135:2;2128:5;2124:14;2120:28;2110:38;;2052:102;;;:::o;2160:377::-;2248:3;2276:39;2309:5;2276:39;:::i;:::-;2331:71;2395:6;2390:3;2331:71;:::i;:::-;2324:78;;2411:65;2469:6;2464:3;2457:4;2450:5;2446:16;2411:65;:::i;:::-;2501:29;2523:6;2501:29;:::i;:::-;2496:3;2492:39;2485:46;;2252:285;2160:377;;;;:::o;2543:313::-;2656:4;2694:2;2683:9;2679:18;2671:26;;2743:9;2737:4;2733:20;2729:1;2718:9;2714:17;2707:47;2771:78;2844:4;2835:6;2771:78;:::i;:::-;2763:86;;2543:313;;;;:::o;2862:77::-;2899:7;2928:5;2917:16;;2862:77;;;:::o;2945:122::-;3018:24;3036:5;3018:24;:::i;:::-;3011:5;3008:35;2998:63;;3057:1;3054;3047:12;2998:63;2945:122;:::o;3073:139::-;3119:5;3157:6;3144:20;3135:29;;3173:33;3200:5;3173:33;:::i;:::-;3073:139;;;;:::o;3218:329::-;3277:6;3326:2;3314:9;3305:7;3301:23;3297:32;3294:119;;;3332:79;;:::i;:::-;3294:119;3452:1;3477:53;3522:7;3513:6;3502:9;3498:22;3477:53;:::i;:::-;3467:63;;3423:117;3218:329;;;;:::o;3553:126::-;3590:7;3630:42;3623:5;3619:54;3608:65;;3553:126;;;:::o;3685:96::-;3722:7;3751:24;3769:5;3751:24;:::i;:::-;3740:35;;3685:96;;;:::o;3787:118::-;3874:24;3892:5;3874:24;:::i;:::-;3869:3;3862:37;3787:118;;:::o;3911:222::-;4004:4;4042:2;4031:9;4027:18;4019:26;;4055:71;4123:1;4112:9;4108:17;4099:6;4055:71;:::i;:::-;3911:222;;;;:::o;4139:122::-;4212:24;4230:5;4212:24;:::i;:::-;4205:5;4202:35;4192:63;;4251:1;4248;4241:12;4192:63;4139:122;:::o;4267:139::-;4313:5;4351:6;4338:20;4329:29;;4367:33;4394:5;4367:33;:::i;:::-;4267:139;;;;:::o;4412:474::-;4480:6;4488;4537:2;4525:9;4516:7;4512:23;4508:32;4505:119;;;4543:79;;:::i;:::-;4505:119;4663:1;4688:53;4733:7;4724:6;4713:9;4709:22;4688:53;:::i;:::-;4678:63;;4634:117;4790:2;4816:53;4861:7;4852:6;4841:9;4837:22;4816:53;:::i;:::-;4806:63;;4761:118;4412:474;;;;;:::o;4892:118::-;4979:24;4997:5;4979:24;:::i;:::-;4974:3;4967:37;4892:118;;:::o;5016:222::-;5109:4;5147:2;5136:9;5132:18;5124:26;;5160:71;5228:1;5217:9;5213:17;5204:6;5160:71;:::i;:::-;5016:222;;;;:::o;5244:117::-;5353:1;5350;5343:12;5367:117;5476:1;5473;5466:12;5490:180;5538:77;5535:1;5528:88;5635:4;5632:1;5625:15;5659:4;5656:1;5649:15;5676:281;5759:27;5781:4;5759:27;:::i;:::-;5751:6;5747:40;5889:6;5877:10;5874:22;5853:18;5841:10;5838:34;5835:62;5832:88;;;5900:18;;:::i;:::-;5832:88;5940:10;5936:2;5929:22;5719:238;5676:281;;:::o;5963:129::-;5997:6;6024:20;;:::i;:::-;6014:30;;6053:33;6081:4;6073:6;6053:33;:::i;:::-;5963:129;;;:::o;6098:308::-;6160:4;6250:18;6242:6;6239:30;6236:56;;;6272:18;;:::i;:::-;6236:56;6310:29;6332:6;6310:29;:::i;:::-;6302:37;;6394:4;6388;6384:15;6376:23;;6098:308;;;:::o;6412:148::-;6510:6;6505:3;6500;6487:30;6551:1;6542:6;6537:3;6533:16;6526:27;6412:148;;;:::o;6566:425::-;6644:5;6669:66;6685:49;6727:6;6685:49;:::i;:::-;6669:66;:::i;:::-;6660:75;;6758:6;6751:5;6744:21;6796:4;6789:5;6785:16;6834:3;6825:6;6820:3;6816:16;6813:25;6810:112;;;6841:79;;:::i;:::-;6810:112;6931:54;6978:6;6973:3;6968;6931:54;:::i;:::-;6650:341;6566:425;;;;;:::o;7011:340::-;7067:5;7116:3;7109:4;7101:6;7097:17;7093:27;7083:122;;7124:79;;:::i;:::-;7083:122;7241:6;7228:20;7266:79;7341:3;7333:6;7326:4;7318:6;7314:17;7266:79;:::i;:::-;7257:88;;7073:278;7011:340;;;;:::o;7357:509::-;7426:6;7475:2;7463:9;7454:7;7450:23;7446:32;7443:119;;;7481:79;;:::i;:::-;7443:119;7629:1;7618:9;7614:17;7601:31;7659:18;7651:6;7648:30;7645:117;;;7681:79;;:::i;:::-;7645:117;7786:63;7841:7;7832:6;7821:9;7817:22;7786:63;:::i;:::-;7776:73;;7572:287;7357:509;;;;:::o;7872:116::-;7942:21;7957:5;7942:21;:::i;:::-;7935:5;7932:32;7922:60;;7978:1;7975;7968:12;7922:60;7872:116;:::o;7994:133::-;8037:5;8075:6;8062:20;8053:29;;8091:30;8115:5;8091:30;:::i;:::-;7994:133;;;;:::o;8133:323::-;8189:6;8238:2;8226:9;8217:7;8213:23;8209:32;8206:119;;;8244:79;;:::i;:::-;8206:119;8364:1;8389:50;8431:7;8422:6;8411:9;8407:22;8389:50;:::i;:::-;8379:60;;8335:114;8133:323;;;;:::o;8462:619::-;8539:6;8547;8555;8604:2;8592:9;8583:7;8579:23;8575:32;8572:119;;;8610:79;;:::i;:::-;8572:119;8730:1;8755:53;8800:7;8791:6;8780:9;8776:22;8755:53;:::i;:::-;8745:63;;8701:117;8857:2;8883:53;8928:7;8919:6;8908:9;8904:22;8883:53;:::i;:::-;8873:63;;8828:118;8985:2;9011:53;9056:7;9047:6;9036:9;9032:22;9011:53;:::i;:::-;9001:63;;8956:118;8462:619;;;;;:::o;9087:474::-;9155:6;9163;9212:2;9200:9;9191:7;9187:23;9183:32;9180:119;;;9218:79;;:::i;:::-;9180:119;9338:1;9363:53;9408:7;9399:6;9388:9;9384:22;9363:53;:::i;:::-;9353:63;;9309:117;9465:2;9491:53;9536:7;9527:6;9516:9;9512:22;9491:53;:::i;:::-;9481:63;;9436:118;9087:474;;;;;:::o;9567:332::-;9688:4;9726:2;9715:9;9711:18;9703:26;;9739:71;9807:1;9796:9;9792:17;9783:6;9739:71;:::i;:::-;9820:72;9888:2;9877:9;9873:18;9864:6;9820:72;:::i;:::-;9567:332;;;;;:::o;9905:117::-;10014:1;10011;10004:12;10028:117;10137:1;10134;10127:12;10168:568;10241:8;10251:6;10301:3;10294:4;10286:6;10282:17;10278:27;10268:122;;10309:79;;:::i;:::-;10268:122;10422:6;10409:20;10399:30;;10452:18;10444:6;10441:30;10438:117;;;10474:79;;:::i;:::-;10438:117;10588:4;10580:6;10576:17;10564:29;;10642:3;10634:4;10626:6;10622:17;10612:8;10608:32;10605:41;10602:128;;;10649:79;;:::i;:::-;10602:128;10168:568;;;;;:::o;10742:559::-;10828:6;10836;10885:2;10873:9;10864:7;10860:23;10856:32;10853:119;;;10891:79;;:::i;:::-;10853:119;11039:1;11028:9;11024:17;11011:31;11069:18;11061:6;11058:30;11055:117;;;11091:79;;:::i;:::-;11055:117;11204:80;11276:7;11267:6;11256:9;11252:22;11204:80;:::i;:::-;11186:98;;;;10982:312;10742:559;;;;;:::o;11307:146::-;11406:6;11440:5;11434:12;11424:22;;11307:146;;;:::o;11459:216::-;11590:11;11624:6;11619:3;11612:19;11664:4;11659:3;11655:14;11640:29;;11459:216;;;;:::o;11681:164::-;11780:4;11803:3;11795:11;;11833:4;11828:3;11824:14;11816:22;;11681:164;;;:::o;11851:108::-;11928:24;11946:5;11928:24;:::i;:::-;11923:3;11916:37;11851:108;;:::o;11965:101::-;12001:7;12041:18;12034:5;12030:30;12019:41;;11965:101;;;:::o;12072:105::-;12147:23;12164:5;12147:23;:::i;:::-;12142:3;12135:36;12072:105;;:::o;12183:99::-;12254:21;12269:5;12254:21;:::i;:::-;12249:3;12242:34;12183:99;;:::o;12288:91::-;12324:7;12364:8;12357:5;12353:20;12342:31;;12288:91;;;:::o;12385:105::-;12460:23;12477:5;12460:23;:::i;:::-;12455:3;12448:36;12385:105;;:::o;12568:866::-;12719:4;12714:3;12710:14;12806:4;12799:5;12795:16;12789:23;12825:63;12882:4;12877:3;12873:14;12859:12;12825:63;:::i;:::-;12734:164;12990:4;12983:5;12979:16;12973:23;13009:61;13064:4;13059:3;13055:14;13041:12;13009:61;:::i;:::-;12908:172;13164:4;13157:5;13153:16;13147:23;13183:57;13234:4;13229:3;13225:14;13211:12;13183:57;:::i;:::-;13090:160;13337:4;13330:5;13326:16;13320:23;13356:61;13411:4;13406:3;13402:14;13388:12;13356:61;:::i;:::-;13260:167;12688:746;12568:866;;:::o;13440:307::-;13573:10;13594:110;13700:3;13692:6;13594:110;:::i;:::-;13736:4;13731:3;13727:14;13713:28;;13440:307;;;;:::o;13753:145::-;13855:4;13887;13882:3;13878:14;13870:22;;13753:145;;;:::o;13980:988::-;14163:3;14192:86;14272:5;14192:86;:::i;:::-;14294:118;14405:6;14400:3;14294:118;:::i;:::-;14287:125;;14436:88;14518:5;14436:88;:::i;:::-;14547:7;14578:1;14563:380;14588:6;14585:1;14582:13;14563:380;;;14664:6;14658:13;14691:127;14814:3;14799:13;14691:127;:::i;:::-;14684:134;;14841:92;14926:6;14841:92;:::i;:::-;14831:102;;14623:320;14610:1;14607;14603:9;14598:14;;14563:380;;;14567:14;14959:3;14952:10;;14168:800;;;13980:988;;;;:::o;14974:501::-;15181:4;15219:2;15208:9;15204:18;15196:26;;15268:9;15262:4;15258:20;15254:1;15243:9;15239:17;15232:47;15296:172;15463:4;15454:6;15296:172;:::i;:::-;15288:180;;14974:501;;;;:::o;15481:329::-;15540:6;15589:2;15577:9;15568:7;15564:23;15560:32;15557:119;;;15595:79;;:::i;:::-;15557:119;15715:1;15740:53;15785:7;15776:6;15765:9;15761:22;15740:53;:::i;:::-;15730:63;;15686:117;15481:329;;;;:::o;15816:114::-;15883:6;15917:5;15911:12;15901:22;;15816:114;;;:::o;15936:184::-;16035:11;16069:6;16064:3;16057:19;16109:4;16104:3;16100:14;16085:29;;15936:184;;;;:::o;16126:132::-;16193:4;16216:3;16208:11;;16246:4;16241:3;16237:14;16229:22;;16126:132;;;:::o;16264:108::-;16341:24;16359:5;16341:24;:::i;:::-;16336:3;16329:37;16264:108;;:::o;16378:179::-;16447:10;16468:46;16510:3;16502:6;16468:46;:::i;:::-;16546:4;16541:3;16537:14;16523:28;;16378:179;;;;:::o;16563:113::-;16633:4;16665;16660:3;16656:14;16648:22;;16563:113;;;:::o;16712:732::-;16831:3;16860:54;16908:5;16860:54;:::i;:::-;16930:86;17009:6;17004:3;16930:86;:::i;:::-;16923:93;;17040:56;17090:5;17040:56;:::i;:::-;17119:7;17150:1;17135:284;17160:6;17157:1;17154:13;17135:284;;;17236:6;17230:13;17263:63;17322:3;17307:13;17263:63;:::i;:::-;17256:70;;17349:60;17402:6;17349:60;:::i;:::-;17339:70;;17195:224;17182:1;17179;17175:9;17170:14;;17135:284;;;17139:14;17435:3;17428:10;;16836:608;;;16712:732;;;;:::o;17450:373::-;17593:4;17631:2;17620:9;17616:18;17608:26;;17680:9;17674:4;17670:20;17666:1;17655:9;17651:17;17644:47;17708:108;17811:4;17802:6;17708:108;:::i;:::-;17700:116;;17450:373;;;;:::o;17829:619::-;17906:6;17914;17922;17971:2;17959:9;17950:7;17946:23;17942:32;17939:119;;;17977:79;;:::i;:::-;17939:119;18097:1;18122:53;18167:7;18158:6;18147:9;18143:22;18122:53;:::i;:::-;18112:63;;18068:117;18224:2;18250:53;18295:7;18286:6;18275:9;18271:22;18250:53;:::i;:::-;18240:63;;18195:118;18352:2;18378:53;18423:7;18414:6;18403:9;18399:22;18378:53;:::i;:::-;18368:63;;18323:118;17829:619;;;;;:::o;18454:468::-;18519:6;18527;18576:2;18564:9;18555:7;18551:23;18547:32;18544:119;;;18582:79;;:::i;:::-;18544:119;18702:1;18727:53;18772:7;18763:6;18752:9;18748:22;18727:53;:::i;:::-;18717:63;;18673:117;18829:2;18855:50;18897:7;18888:6;18877:9;18873:22;18855:50;:::i;:::-;18845:60;;18800:115;18454:468;;;;;:::o;18928:307::-;18989:4;19079:18;19071:6;19068:30;19065:56;;;19101:18;;:::i;:::-;19065:56;19139:29;19161:6;19139:29;:::i;:::-;19131:37;;19223:4;19217;19213:15;19205:23;;18928:307;;;:::o;19241:423::-;19318:5;19343:65;19359:48;19400:6;19359:48;:::i;:::-;19343:65;:::i;:::-;19334:74;;19431:6;19424:5;19417:21;19469:4;19462:5;19458:16;19507:3;19498:6;19493:3;19489:16;19486:25;19483:112;;;19514:79;;:::i;:::-;19483:112;19604:54;19651:6;19646:3;19641;19604:54;:::i;:::-;19324:340;19241:423;;;;;:::o;19683:338::-;19738:5;19787:3;19780:4;19772:6;19768:17;19764:27;19754:122;;19795:79;;:::i;:::-;19754:122;19912:6;19899:20;19937:78;20011:3;20003:6;19996:4;19988:6;19984:17;19937:78;:::i;:::-;19928:87;;19744:277;19683:338;;;;:::o;20027:943::-;20122:6;20130;20138;20146;20195:3;20183:9;20174:7;20170:23;20166:33;20163:120;;;20202:79;;:::i;:::-;20163:120;20322:1;20347:53;20392:7;20383:6;20372:9;20368:22;20347:53;:::i;:::-;20337:63;;20293:117;20449:2;20475:53;20520:7;20511:6;20500:9;20496:22;20475:53;:::i;:::-;20465:63;;20420:118;20577:2;20603:53;20648:7;20639:6;20628:9;20624:22;20603:53;:::i;:::-;20593:63;;20548:118;20733:2;20722:9;20718:18;20705:32;20764:18;20756:6;20753:30;20750:117;;;20786:79;;:::i;:::-;20750:117;20891:62;20945:7;20936:6;20925:9;20921:22;20891:62;:::i;:::-;20881:72;;20676:287;20027:943;;;;;;;:::o;21048:876::-;21209:4;21204:3;21200:14;21296:4;21289:5;21285:16;21279:23;21315:63;21372:4;21367:3;21363:14;21349:12;21315:63;:::i;:::-;21224:164;21480:4;21473:5;21469:16;21463:23;21499:61;21554:4;21549:3;21545:14;21531:12;21499:61;:::i;:::-;21398:172;21654:4;21647:5;21643:16;21637:23;21673:57;21724:4;21719:3;21715:14;21701:12;21673:57;:::i;:::-;21580:160;21827:4;21820:5;21816:16;21810:23;21846:61;21901:4;21896:3;21892:14;21878:12;21846:61;:::i;:::-;21750:167;21178:746;21048:876;;:::o;21930:351::-;22087:4;22125:3;22114:9;22110:19;22102:27;;22139:135;22271:1;22260:9;22256:17;22247:6;22139:135;:::i;:::-;21930:351;;;;:::o;22287:474::-;22355:6;22363;22412:2;22400:9;22391:7;22387:23;22383:32;22380:119;;;22418:79;;:::i;:::-;22380:119;22538:1;22563:53;22608:7;22599:6;22588:9;22584:22;22563:53;:::i;:::-;22553:63;;22509:117;22665:2;22691:53;22736:7;22727:6;22716:9;22712:22;22691:53;:::i;:::-;22681:63;;22636:118;22287:474;;;;;:::o;22767:::-;22835:6;22843;22892:2;22880:9;22871:7;22867:23;22863:32;22860:119;;;22898:79;;:::i;:::-;22860:119;23018:1;23043:53;23088:7;23079:6;23068:9;23064:22;23043:53;:::i;:::-;23033:63;;22989:117;23145:2;23171:53;23216:7;23207:6;23196:9;23192:22;23171:53;:::i;:::-;23161:63;;23116:118;22767:474;;;;;:::o;23247:180::-;23295:77;23292:1;23285:88;23392:4;23389:1;23382:15;23416:4;23413:1;23406:15;23433:320;23477:6;23514:1;23508:4;23504:12;23494:22;;23561:1;23555:4;23551:12;23582:18;23572:81;;23638:4;23630:6;23626:17;23616:27;;23572:81;23700:2;23692:6;23689:14;23669:18;23666:38;23663:84;;23719:18;;:::i;:::-;23663:84;23484:269;23433:320;;;:::o;23759:141::-;23808:4;23831:3;23823:11;;23854:3;23851:1;23844:14;23888:4;23885:1;23875:18;23867:26;;23759:141;;;:::o;23906:93::-;23943:6;23990:2;23985;23978:5;23974:14;23970:23;23960:33;;23906:93;;;:::o;24005:107::-;24049:8;24099:5;24093:4;24089:16;24068:37;;24005:107;;;;:::o;24118:393::-;24187:6;24237:1;24225:10;24221:18;24260:97;24290:66;24279:9;24260:97;:::i;:::-;24378:39;24408:8;24397:9;24378:39;:::i;:::-;24366:51;;24450:4;24446:9;24439:5;24435:21;24426:30;;24499:4;24489:8;24485:19;24478:5;24475:30;24465:40;;24194:317;;24118:393;;;;;:::o;24517:60::-;24545:3;24566:5;24559:12;;24517:60;;;:::o;24583:142::-;24633:9;24666:53;24684:34;24693:24;24711:5;24693:24;:::i;:::-;24684:34;:::i;:::-;24666:53;:::i;:::-;24653:66;;24583:142;;;:::o;24731:75::-;24774:3;24795:5;24788:12;;24731:75;;;:::o;24812:269::-;24922:39;24953:7;24922:39;:::i;:::-;24983:91;25032:41;25056:16;25032:41;:::i;:::-;25024:6;25017:4;25011:11;24983:91;:::i;:::-;24977:4;24970:105;24888:193;24812:269;;;:::o;25087:73::-;25132:3;25087:73;:::o;25166:189::-;25243:32;;:::i;:::-;25284:65;25342:6;25334;25328:4;25284:65;:::i;:::-;25219:136;25166:189;;:::o;25361:186::-;25421:120;25438:3;25431:5;25428:14;25421:120;;;25492:39;25529:1;25522:5;25492:39;:::i;:::-;25465:1;25458:5;25454:13;25445:22;;25421:120;;;25361:186;;:::o;25553:543::-;25654:2;25649:3;25646:11;25643:446;;;25688:38;25720:5;25688:38;:::i;:::-;25772:29;25790:10;25772:29;:::i;:::-;25762:8;25758:44;25955:2;25943:10;25940:18;25937:49;;;25976:8;25961:23;;25937:49;25999:80;26055:22;26073:3;26055:22;:::i;:::-;26045:8;26041:37;26028:11;25999:80;:::i;:::-;25658:431;;25643:446;25553:543;;;:::o;26102:117::-;26156:8;26206:5;26200:4;26196:16;26175:37;;26102:117;;;;:::o;26225:169::-;26269:6;26302:51;26350:1;26346:6;26338:5;26335:1;26331:13;26302:51;:::i;:::-;26298:56;26383:4;26377;26373:15;26363:25;;26276:118;26225:169;;;;:::o;26399:295::-;26475:4;26621:29;26646:3;26640:4;26621:29;:::i;:::-;26613:37;;26683:3;26680:1;26676:11;26670:4;26667:21;26659:29;;26399:295;;;;:::o;26699:1395::-;26816:37;26849:3;26816:37;:::i;:::-;26918:18;26910:6;26907:30;26904:56;;;26940:18;;:::i;:::-;26904:56;26984:38;27016:4;27010:11;26984:38;:::i;:::-;27069:67;27129:6;27121;27115:4;27069:67;:::i;:::-;27163:1;27187:4;27174:17;;27219:2;27211:6;27208:14;27236:1;27231:618;;;;27893:1;27910:6;27907:77;;;27959:9;27954:3;27950:19;27944:26;27935:35;;27907:77;28010:67;28070:6;28063:5;28010:67;:::i;:::-;28004:4;27997:81;27866:222;27201:887;;27231:618;27283:4;27279:9;27271:6;27267:22;27317:37;27349:4;27317:37;:::i;:::-;27376:1;27390:208;27404:7;27401:1;27398:14;27390:208;;;27483:9;27478:3;27474:19;27468:26;27460:6;27453:42;27534:1;27526:6;27522:14;27512:24;;27581:2;27570:9;27566:18;27553:31;;27427:4;27424:1;27420:12;27415:17;;27390:208;;;27626:6;27617:7;27614:19;27611:179;;;27684:9;27679:3;27675:19;27669:26;27727:48;27769:4;27761:6;27757:17;27746:9;27727:48;:::i;:::-;27719:6;27712:64;27634:156;27611:179;27836:1;27832;27824:6;27820:14;27816:22;27810:4;27803:36;27238:611;;;27201:887;;26791:1303;;;26699:1395;;:::o;28100:180::-;28148:77;28145:1;28138:88;28245:4;28242:1;28235:15;28269:4;28266:1;28259:15;28286:410;28326:7;28349:20;28367:1;28349:20;:::i;:::-;28344:25;;28383:20;28401:1;28383:20;:::i;:::-;28378:25;;28438:1;28435;28431:9;28460:30;28478:11;28460:30;:::i;:::-;28449:41;;28639:1;28630:7;28626:15;28623:1;28620:22;28600:1;28593:9;28573:83;28550:139;;28669:18;;:::i;:::-;28550:139;28334:362;28286:410;;;;:::o;28702:180::-;28750:77;28747:1;28740:88;28847:4;28844:1;28837:15;28871:4;28868:1;28861:15;28888:185;28928:1;28945:20;28963:1;28945:20;:::i;:::-;28940:25;;28979:20;28997:1;28979:20;:::i;:::-;28974:25;;29018:1;29008:35;;29023:18;;:::i;:::-;29008:35;29065:1;29062;29058:9;29053:14;;28888:185;;;;:::o;29079:147::-;29180:11;29217:3;29202:18;;29079:147;;;;:::o;29232:114::-;;:::o;29352:398::-;29511:3;29532:83;29613:1;29608:3;29532:83;:::i;:::-;29525:90;;29624:93;29713:3;29624:93;:::i;:::-;29742:1;29737:3;29733:11;29726:18;;29352:398;;;:::o;29756:379::-;29940:3;29962:147;30105:3;29962:147;:::i;:::-;29955:154;;30126:3;30119:10;;29756:379;;;:::o;30141:165::-;30281:17;30277:1;30269:6;30265:14;30258:41;30141:165;:::o;30312:366::-;30454:3;30475:67;30539:2;30534:3;30475:67;:::i;:::-;30468:74;;30551:93;30640:3;30551:93;:::i;:::-;30669:2;30664:3;30660:12;30653:19;;30312:366;;;:::o;30684:419::-;30850:4;30888:2;30877:9;30873:18;30865:26;;30937:9;30931:4;30927:20;30923:1;30912:9;30908:17;30901:47;30965:131;31091:4;30965:131;:::i;:::-;30957:139;;30684:419;;;:::o;31109:227::-;31249:34;31245:1;31237:6;31233:14;31226:58;31318:10;31313:2;31305:6;31301:15;31294:35;31109:227;:::o;31342:366::-;31484:3;31505:67;31569:2;31564:3;31505:67;:::i;:::-;31498:74;;31581:93;31670:3;31581:93;:::i;:::-;31699:2;31694:3;31690:12;31683:19;;31342:366;;;:::o;31714:419::-;31880:4;31918:2;31907:9;31903:18;31895:26;;31967:9;31961:4;31957:20;31953:1;31942:9;31938:17;31931:47;31995:131;32121:4;31995:131;:::i;:::-;31987:139;;31714:419;;;:::o;32139:170::-;32279:22;32275:1;32267:6;32263:14;32256:46;32139:170;:::o;32315:366::-;32457:3;32478:67;32542:2;32537:3;32478:67;:::i;:::-;32471:74;;32554:93;32643:3;32554:93;:::i;:::-;32672:2;32667:3;32663:12;32656:19;;32315:366;;;:::o;32687:419::-;32853:4;32891:2;32880:9;32876:18;32868:26;;32940:9;32934:4;32930:20;32926:1;32915:9;32911:17;32904:47;32968:131;33094:4;32968:131;:::i;:::-;32960:139;;32687:419;;;:::o;33112:191::-;33152:3;33171:20;33189:1;33171:20;:::i;:::-;33166:25;;33205:20;33223:1;33205:20;:::i;:::-;33200:25;;33248:1;33245;33241:9;33234:16;;33269:3;33266:1;33263:10;33260:36;;;33276:18;;:::i;:::-;33260:36;33112:191;;;;:::o;33309:170::-;33449:22;33445:1;33437:6;33433:14;33426:46;33309:170;:::o;33485:366::-;33627:3;33648:67;33712:2;33707:3;33648:67;:::i;:::-;33641:74;;33724:93;33813:3;33724:93;:::i;:::-;33842:2;33837:3;33833:12;33826:19;;33485:366;;;:::o;33857:419::-;34023:4;34061:2;34050:9;34046:18;34038:26;;34110:9;34104:4;34100:20;34096:1;34085:9;34081:17;34074:47;34138:131;34264:4;34138:131;:::i;:::-;34130:139;;33857:419;;;:::o;34282:169::-;34422:21;34418:1;34410:6;34406:14;34399:45;34282:169;:::o;34457:366::-;34599:3;34620:67;34684:2;34679:3;34620:67;:::i;:::-;34613:74;;34696:93;34785:3;34696:93;:::i;:::-;34814:2;34809:3;34805:12;34798:19;;34457:366;;;:::o;34829:419::-;34995:4;35033:2;35022:9;35018:18;35010:26;;35082:9;35076:4;35072:20;35068:1;35057:9;35053:17;35046:47;35110:131;35236:4;35110:131;:::i;:::-;35102:139;;34829:419;;;:::o;35254:173::-;35394:25;35390:1;35382:6;35378:14;35371:49;35254:173;:::o;35433:366::-;35575:3;35596:67;35660:2;35655:3;35596:67;:::i;:::-;35589:74;;35672:93;35761:3;35672:93;:::i;:::-;35790:2;35785:3;35781:12;35774:19;;35433:366;;;:::o;35805:419::-;35971:4;36009:2;35998:9;35994:18;35986:26;;36058:9;36052:4;36048:20;36044:1;36033:9;36029:17;36022:47;36086:131;36212:4;36086:131;:::i;:::-;36078:139;;35805:419;;;:::o;36230:234::-;36370:34;36366:1;36358:6;36354:14;36347:58;36439:17;36434:2;36426:6;36422:15;36415:42;36230:234;:::o;36470:366::-;36612:3;36633:67;36697:2;36692:3;36633:67;:::i;:::-;36626:74;;36709:93;36798:3;36709:93;:::i;:::-;36827:2;36822:3;36818:12;36811:19;;36470:366;;;:::o;36842:419::-;37008:4;37046:2;37035:9;37031:18;37023:26;;37095:9;37089:4;37085:20;37081:1;37070:9;37066:17;37059:47;37123:131;37249:4;37123:131;:::i;:::-;37115:139;;36842:419;;;:::o;37267:148::-;37369:11;37406:3;37391:18;;37267:148;;;;:::o;37421:390::-;37527:3;37555:39;37588:5;37555:39;:::i;:::-;37610:89;37692:6;37687:3;37610:89;:::i;:::-;37603:96;;37708:65;37766:6;37761:3;37754:4;37747:5;37743:16;37708:65;:::i;:::-;37798:6;37793:3;37789:16;37782:23;;37531:280;37421:390;;;;:::o;37841:874::-;37944:3;37981:5;37975:12;38010:36;38036:9;38010:36;:::i;:::-;38062:89;38144:6;38139:3;38062:89;:::i;:::-;38055:96;;38182:1;38171:9;38167:17;38198:1;38193:166;;;;38373:1;38368:341;;;;38160:549;;38193:166;38277:4;38273:9;38262;38258:25;38253:3;38246:38;38339:6;38332:14;38325:22;38317:6;38313:35;38308:3;38304:45;38297:52;;38193:166;;38368:341;38435:38;38467:5;38435:38;:::i;:::-;38495:1;38509:154;38523:6;38520:1;38517:13;38509:154;;;38597:7;38591:14;38587:1;38582:3;38578:11;38571:35;38647:1;38638:7;38634:15;38623:26;;38545:4;38542:1;38538:12;38533:17;;38509:154;;;38692:6;38687:3;38683:16;38676:23;;38375:334;;38160:549;;37948:767;;37841:874;;;;:::o;38721:589::-;38946:3;38968:95;39059:3;39050:6;38968:95;:::i;:::-;38961:102;;39080:95;39171:3;39162:6;39080:95;:::i;:::-;39073:102;;39192:92;39280:3;39271:6;39192:92;:::i;:::-;39185:99;;39301:3;39294:10;;38721:589;;;;;;:::o;39316:171::-;39355:3;39378:24;39396:5;39378:24;:::i;:::-;39369:33;;39424:4;39417:5;39414:15;39411:41;;39432:18;;:::i;:::-;39411:41;39479:1;39472:5;39468:13;39461:20;;39316:171;;;:::o;39493:98::-;39544:6;39578:5;39572:12;39562:22;;39493:98;;;:::o;39597:168::-;39680:11;39714:6;39709:3;39702:19;39754:4;39749:3;39745:14;39730:29;;39597:168;;;;:::o;39771:373::-;39857:3;39885:38;39917:5;39885:38;:::i;:::-;39939:70;40002:6;39997:3;39939:70;:::i;:::-;39932:77;;40018:65;40076:6;40071:3;40064:4;40057:5;40053:16;40018:65;:::i;:::-;40108:29;40130:6;40108:29;:::i;:::-;40103:3;40099:39;40092:46;;39861:283;39771:373;;;;:::o;40150:640::-;40345:4;40383:3;40372:9;40368:19;40360:27;;40397:71;40465:1;40454:9;40450:17;40441:6;40397:71;:::i;:::-;40478:72;40546:2;40535:9;40531:18;40522:6;40478:72;:::i;:::-;40560;40628:2;40617:9;40613:18;40604:6;40560:72;:::i;:::-;40679:9;40673:4;40669:20;40664:2;40653:9;40649:18;40642:48;40707:76;40778:4;40769:6;40707:76;:::i;:::-;40699:84;;40150:640;;;;;;;:::o;40796:141::-;40852:5;40883:6;40877:13;40868:22;;40899:32;40925:5;40899:32;:::i;:::-;40796:141;;;;:::o;40943:349::-;41012:6;41061:2;41049:9;41040:7;41036:23;41032:32;41029:119;;;41067:79;;:::i;:::-;41029:119;41187:1;41212:63;41267:7;41258:6;41247:9;41243:22;41212:63;:::i;:::-;41202:73;;41158:127;40943:349;;;;:::o
Swarm Source
ipfs://cdd3a427bc75354e732226c42cc1dd4859a936a190695fec7921723072aefb1c
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.