Overview
TokenID
126
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
MetaLifeResidence
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-02-03 */ // File: @openzeppelin/contracts/utils/math/Math.sol // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); 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 overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { 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 division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return 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. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev 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^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + 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^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 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^256 / 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^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. 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^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // 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^256. Since the preconditions guarantee that the outcome is // less than 2^256, 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; } } /** * @notice 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) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @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; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @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; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @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; } } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return 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 { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; /** * @dev String operations. */ library Strings { 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 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; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { 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 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)); } } // File: @openzeppelin/contracts/utils/Context.sol // 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; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; /** * @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); } } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v5.0.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 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; } } // File: contracts/ERC721.sol pragma solidity ^0.8.4; /// @notice Simple ERC721 implementation with storage hitchhiking. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC721.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721/ERC721.sol) /// /// @dev Note: /// The ERC721 standard allows for self-approvals. /// For performance, this implementation WILL NOT revert for such actions. /// Please add any checks with overrides if desired. abstract contract ERC721 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev An account can hold up to 4294967295 tokens. uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Only the token owner or an approved account can manage the token. error NotOwnerNorApproved(); /// @dev The token does not exist. error TokenDoesNotExist(); /// @dev The token already exists. error TokenAlreadyExists(); /// @dev Cannot query the balance for the zero address. error BalanceQueryForZeroAddress(); /// @dev Cannot mint or transfer to the zero address. error TransferToZeroAddress(); /// @dev The token must be owned by `from`. error TransferFromIncorrectOwner(); /// @dev The recipient's balance has overflowed. error AccountBalanceOverflow(); /// @dev Cannot safely transfer to a contract that does not implement /// the ERC721Receiver interface. error TransferToNonERC721ReceiverImplementer(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when token `id` is transferred from `from` to `to`. event Transfer(address indexed from, address indexed to, uint256 indexed id); /// @dev Emitted when `owner` enables `account` to manage the `id` token. event Approval(address indexed owner, address indexed account, uint256 indexed id); /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens. event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved); /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`. uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`. uint256 private constant _APPROVAL_EVENT_SIGNATURE = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925; /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`. uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE = 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership data slot of `id` is given by: /// ``` /// mstore(0x00, id) /// mstore(0x1c, _ERC721_MASTER_SLOT_SEED) /// let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) /// ``` /// Bits Layout: // - [0..159] `addr` // - [160..223] `extraData` /// /// The approved address slot is given by: `add(1, ownershipSlot)`. /// /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip /// /// The balance slot of `owner` is given by: /// ``` /// mstore(0x1c, _ERC721_MASTER_SLOT_SEED) /// mstore(0x00, owner) /// let balanceSlot := keccak256(0x0c, 0x1c) /// ``` /// Bits Layout: /// - [0..31] `balance` /// - [32..225] `aux` /// /// The `operator` approval slot of `owner` is given by: /// ``` /// mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator)) /// mstore(0x00, owner) /// let operatorApprovalSlot := keccak256(0x0c, 0x30) /// ``` uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192; /// @dev Pre-shifted and pre-masked constant. uint256 private constant _ERC721_MASTER_SLOT_SEED_MASKED = 0x0a5a2e7a00000000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC721 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the token collection name. function name() public view virtual returns (string memory); /// @dev Returns the token collection symbol. function symbol() public view virtual returns (string memory); /// @dev Returns the Uniform Resource Identifier (URI) for token `id`. function tokenURI(uint256 id) public view virtual returns (string memory); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC721 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of token `id`. /// /// Requirements: /// - Token `id` must exist. function ownerOf(uint256 id) public view virtual returns (address result) { result = _ownerOf(id); /// @solidity memory-safe-assembly assembly { if iszero(result) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } } } /// @dev Returns the number of tokens owned by `owner`. /// /// Requirements: /// - `owner` must not be the zero address. function balanceOf(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Revert if the `owner` is the zero address. if iszero(owner) { mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`. revert(0x1c, 0x04) } mstore(0x1c, _ERC721_MASTER_SLOT_SEED) mstore(0x00, owner) result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE) } } /// @dev Returns the account approved to managed token `id`. /// /// Requirements: /// - Token `id` must exist. function getApproved(uint256 id) public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) if iszero(shr(96, shl(96, sload(ownershipSlot)))) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } result := sload(add(1, ownershipSlot)) } } /// @dev Sets `account` as the approved account to manage token `id`. /// /// Requirements: /// - Token `id` must exist. /// - The caller must be the owner of the token, /// or an approved operator for the token owner. /// /// Emits a {Approval} event. function approve(address account, uint256 id) public payable virtual { _approve(msg.sender, account, id); } /// @dev Returns whether `operator` is approved to manage the tokens of `owner`. function isApprovedForAll(address owner, address operator) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { mstore(0x1c, operator) mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x30)) } } /// @dev Sets whether `operator` is approved to manage the tokens of the caller. /// /// Emits a {ApprovalForAll} event. function setApprovalForAll(address operator, bool isApproved) public virtual { /// @solidity memory-safe-assembly assembly { // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`msg.sender`, `operator`). mstore(0x1c, operator) mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x30), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) log3( 0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator)) ) } } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - The caller must be the owner of the token, or be approved to manage the token. /// /// Emits a {Transfer} event. function transferFrom(address from, address to, uint256 id) public payable virtual { _beforeTokenTransfer(from, to, id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. let bitmaskAddress := shr(96, not(0)) from := and(bitmaskAddress, from) to := and(bitmaskAddress, to) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller())) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) let owner := and(bitmaskAddress, ownershipPacked) // Revert if `from` is not the owner, or does not exist. if iszero(mul(owner, eq(owner, from))) { if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`. revert(0x1c, 0x04) } // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Load, check, and update the token approval. { mstore(0x00, from) let approvedAddress := sload(add(1, ownershipSlot)) // Revert if the caller is not the owner, nor approved. if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) { if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Delete the approved address if any. if approvedAddress { sstore(add(1, ownershipSlot), 0) } } // Update with the new owner. sstore(ownershipSlot, xor(ownershipPacked, xor(from, to))) // Decrement the balance of `from`. { let fromBalanceSlot := keccak256(0x0c, 0x1c) sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1)) } // Increment the balance of `to`. { mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x1c) let toBalanceSlotPacked := add(sload(toBalanceSlot), 1) if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceSlotPacked) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id) } _afterTokenTransfer(from, to, id); } /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`. function safeTransferFrom(address from, address to, uint256 id) public payable virtual { transferFrom(from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, ""); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - The caller must be the owner of the token, or be approved to manage the token. /// - 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 id, bytes calldata data) public payable virtual { transferFrom(from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); } /// @dev Returns true if this contract implements the interface defined by `interfaceId`. /// See: https://eips.ethereum.org/EIPS/eip-165 /// This function call must use less than 30000 gas. function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { let s := shr(224, interfaceId) // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f. result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL QUERY FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns if token `id` exists. function _exists(uint256 id) internal view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))) } } /// @dev Returns the owner of token `id`. /// Returns the zero address instead of reverting if the token does not exist. function _ownerOf(uint256 id) internal view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL DATA HITCHHIKING FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the auxiliary data for `owner`. /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data. /// Auxiliary data can be set for any address, even if it does not have any tokens. function _getAux(address owner) internal view virtual returns (uint224 result) { /// @solidity memory-safe-assembly assembly { mstore(0x1c, _ERC721_MASTER_SLOT_SEED) mstore(0x00, owner) result := shr(32, sload(keccak256(0x0c, 0x1c))) } } /// @dev Set the auxiliary data for `owner` to `value`. /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data. /// Auxiliary data can be set for any address, even if it does not have any tokens. function _setAux(address owner, uint224 value) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x1c, _ERC721_MASTER_SLOT_SEED) mstore(0x00, owner) let balanceSlot := keccak256(0x0c, 0x1c) let packed := sload(balanceSlot) sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed))))) } } /// @dev Returns the extra data for token `id`. /// Minting, transferring, burning a token will not change the extra data. /// The extra data can be set on a non-existent token. function _getExtraData(uint256 id) internal view virtual returns (uint96 result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20))))) } } /// @dev Sets the extra data for token `id` to `value`. /// Minting, transferring, burning a token will not change the extra data. /// The extra data can be set on a non-existent token. function _setExtraData(uint256 id, uint96 value) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let packed := sload(ownershipSlot) sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed))))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints token `id` to `to`. /// /// Requirements: /// /// - Token `id` must not exist. /// - `to` cannot be the zero address. /// /// Emits a {Transfer} event. function _mint(address to, uint256 id) internal virtual { _beforeTokenTransfer(address(0), to, id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. to := shr(96, shl(96, to)) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Load the ownership data. mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) // Revert if the token already exists. if shl(96, ownershipPacked) { mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`. revert(0x1c, 0x04) } // Update with the owner. sstore(ownershipSlot, or(ownershipPacked, to)) // Increment the balance of the owner. { mstore(0x00, to) let balanceSlot := keccak256(0x0c, 0x1c) let balanceSlotPacked := add(sload(balanceSlot), 1) if iszero(and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE)) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(balanceSlot, balanceSlotPacked) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id) } _afterTokenTransfer(address(0), to, id); } /// @dev Equivalent to `_safeMint(to, id, "")`. function _safeMint(address to, uint256 id) internal virtual { _safeMint(to, id, ""); } /// @dev Mints token `id` to `to`. /// /// Requirements: /// /// - Token `id` must not exist. /// - `to` cannot be the zero address. /// - If `to` refers to a smart contract, it must implement /// {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. /// /// Emits a {Transfer} event. function _safeMint(address to, uint256 id, bytes memory data) internal virtual { _mint(to, id); if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_burn(address(0), id)`. function _burn(uint256 id) internal virtual { _burn(address(0), id); } /// @dev Destroys token `id`, using `by`. /// /// Requirements: /// /// - Token `id` must exist. /// - If `by` is not the zero address, /// it must be the owner of the token, or be approved to manage the token. /// /// Emits a {Transfer} event. function _burn(address by, uint256 id) internal virtual { address owner = ownerOf(id); _beforeTokenTransfer(owner, address(0), id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. by := shr(96, shl(96, by)) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) // Reload the owner in case it is changed in `_beforeTokenTransfer`. owner := shr(96, shl(96, ownershipPacked)) // Revert if the token does not exist. if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } // Load and check the token approval. { mstore(0x00, owner) let approvedAddress := sload(add(1, ownershipSlot)) // If `by` is not the zero address, do the authorization check. // Revert if the `by` is not the owner, nor approved. if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) { if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Delete the approved address if any. if approvedAddress { sstore(add(1, ownershipSlot), 0) } } // Clear the owner. sstore(ownershipSlot, xor(ownershipPacked, owner)) // Decrement the balance of `owner`. { let balanceSlot := keccak256(0x0c, 0x1c) sstore(balanceSlot, sub(sload(balanceSlot), 1)) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id) } _afterTokenTransfer(owner, address(0), id); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL APPROVAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `account` is the owner of token `id`, or is approved to managed it. /// /// Requirements: /// - Token `id` must exist. function _isApprovedOrOwner(address account, uint256 id) internal view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 // Clear the upper 96 bits. account := shr(96, shl(96, account)) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let owner := shr(96, shl(96, sload(ownershipSlot))) // Revert if the token does not exist. if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } // Check if `account` is the `owner`. if iszero(eq(account, owner)) { mstore(0x00, owner) // Check if `account` is approved to if iszero(sload(keccak256(0x0c, 0x30))) { result := eq(account, sload(add(1, ownershipSlot))) } } } } /// @dev Returns the account approved to manage token `id`. /// Returns the zero address instead of reverting if the token does not exist. function _getApproved(uint256 id) internal view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20))))) } } /// @dev Equivalent to `_approve(address(0), account, id)`. function _approve(address account, uint256 id) internal virtual { _approve(address(0), account, id); } /// @dev Sets `account` as the approved account to manage token `id`, using `by`. /// /// Requirements: /// - Token `id` must exist. /// - If `by` is not the zero address, `by` must be the owner /// or an approved operator for the token owner. /// /// Emits a {Transfer} event. function _approve(address by, address account, uint256 id) internal virtual { assembly { // Clear the upper 96 bits. let bitmaskAddress := shr(96, not(0)) account := and(bitmaskAddress, account) by := and(bitmaskAddress, by) // Load the owner of the token. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let owner := and(bitmaskAddress, sload(ownershipSlot)) // Revert if the token does not exist. if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } // If `by` is not the zero address, do the authorization check. // Revert if `by` is not the owner, nor approved. if iszero(or(iszero(by), eq(by, owner))) { mstore(0x00, owner) if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Sets `account` as the approved account to manage `id`. sstore(add(1, ownershipSlot), account) // Emit the {Approval} event. log4(0x00, 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id) } } /// @dev Approve or remove the `operator` as an operator for `by`, /// without authorization checks. /// /// Emits a {ApprovalForAll} event. function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual { /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. by := shr(96, shl(96, by)) operator := shr(96, shl(96, operator)) // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`by`, `operator`). mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator)) mstore(0x00, by) sstore(keccak256(0x0c, 0x30), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_transfer(address(0), from, to, id)`. function _transfer(address from, address to, uint256 id) internal virtual { _transfer(address(0), from, to, id); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - If `by` is not the zero address, /// it must be the owner of the token, or be approved to manage the token. /// /// Emits a {Transfer} event. function _transfer(address by, address from, address to, uint256 id) internal virtual { _beforeTokenTransfer(from, to, id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. let bitmaskAddress := shr(96, not(0)) from := and(bitmaskAddress, from) to := and(bitmaskAddress, to) by := and(bitmaskAddress, by) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) let owner := and(bitmaskAddress, ownershipPacked) // Revert if `from` is not the owner, or does not exist. if iszero(mul(owner, eq(owner, from))) { if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`. revert(0x1c, 0x04) } // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Load, check, and update the token approval. { mstore(0x00, from) let approvedAddress := sload(add(1, ownershipSlot)) // If `by` is not the zero address, do the authorization check. // Revert if the `by` is not the owner, nor approved. if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) { if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Delete the approved address if any. if approvedAddress { sstore(add(1, ownershipSlot), 0) } } // Update with the new owner. sstore(ownershipSlot, xor(ownershipPacked, xor(from, to))) // Decrement the balance of `from`. { let fromBalanceSlot := keccak256(0x0c, 0x1c) sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1)) } // Increment the balance of `to`. { mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x1c) let toBalanceSlotPacked := add(sload(toBalanceSlot), 1) if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceSlotPacked) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id) } _afterTokenTransfer(from, to, id); } /// @dev Equivalent to `_safeTransfer(from, to, id, "")`. function _safeTransfer(address from, address to, uint256 id) internal virtual { _safeTransfer(from, to, id, ""); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - The caller must be the owner of the token, or be approved to manage the token. /// - If `to` refers to a smart contract, it must implement /// {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. /// /// Emits a {Transfer} event. function _safeTransfer(address from, address to, uint256 id, bytes memory data) internal virtual { _transfer(address(0), from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); } /// @dev Equivalent to `_safeTransfer(by, from, to, id, "")`. function _safeTransfer(address by, address from, address to, uint256 id) internal virtual { _safeTransfer(by, from, to, id, ""); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - If `by` is not the zero address, /// it must be the owner of the token, or be approved to manage the token. /// - If `to` refers to a smart contract, it must implement /// {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. /// /// Emits a {Transfer} event. function _safeTransfer(address by, address from, address to, uint256 id, bytes memory data) internal virtual { _transfer(by, from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS FOR OVERRIDING */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Hook that is called before any token transfers, including minting and burning. function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {} /// @dev Hook that is called after any token transfers, including minting and burning. function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns if `a` has bytecode of non-zero length. function _hasCode(address a) private view returns (bool result) { /// @solidity memory-safe-assembly assembly { result := extcodesize(a) // Can handle dirty upper bits. } } /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`. /// Reverts if the target does not support the function correctly. function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data) private { /// @solidity memory-safe-assembly assembly { // Prepare the calldata. let m := mload(0x40) let onERC721ReceivedSelector := 0x150b7a02 mstore(m, onERC721ReceivedSelector) mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`. mstore(add(m, 0x40), shr(96, shl(96, from))) mstore(add(m, 0x60), id) mstore(add(m, 0x80), 0x80) let n := mload(data) mstore(add(m, 0xa0), n) if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) } // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) { if returndatasize() { // Bubble up the revert if the call reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } mstore(m, 0) } // Load the returndata and compare it. if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) { mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`. revert(0x1c, 0x04) } } } } // File: contracts/LibPRNG.sol pragma solidity ^0.8.4; /// @notice Library for generating psuedorandom numbers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibPRNG.sol) library LibPRNG { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A psuedorandom number state in memory. struct PRNG { uint256 state; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Seeds the `prng` with `state`. function seed(PRNG memory prng, uint256 state) internal pure { /// @solidity memory-safe-assembly assembly { mstore(prng, state) } } /// @dev Returns the next psuedorandom uint256. /// All bits of the returned uint256 pass the NIST Statistical Test Suite. function next(PRNG memory prng) internal pure returns (uint256 result) { // We simply use `keccak256` for a great balance between // runtime gas costs, bytecode size, and statistical properties. // // A high-quality LCG with a 32-byte state // is only about 30% more gas efficient during runtime, // but requires a 32-byte multiplier, which can cause bytecode bloat // when this function is inlined. // // Using this method is about 2x more efficient than // `nextRandomness = uint256(keccak256(abi.encode(randomness)))`. /// @solidity memory-safe-assembly assembly { result := keccak256(prng, 0x20) mstore(prng, result) } } /// @dev Returns a psuedorandom uint256, uniformly distributed /// between 0 (inclusive) and `upper` (exclusive). /// If your modulus is big, this method is recommended /// for uniform sampling to avoid modulo bias. /// For uniform sampling across all uint256 values, /// or for small enough moduli such that the bias is neligible, /// use {next} instead. function uniform(PRNG memory prng, uint256 upper) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := keccak256(prng, 0x20) mstore(prng, result) if iszero(lt(result, mod(sub(0, upper), upper))) { break } } result := mod(result, upper) } } /// @dev Shuffles the array in-place with Fisher-Yates shuffle. function shuffle(PRNG memory prng, uint256[] memory a) internal pure { /// @solidity memory-safe-assembly assembly { let n := mload(a) let w := not(0) let mask := shr(128, w) if n { for { a := add(a, 0x20) } 1 {} { // We can just directly use `keccak256`, cuz // the other approaches don't save much. let r := keccak256(prng, 0x20) mstore(prng, r) // Note that there will be a very tiny modulo bias // if the length of the array is not a power of 2. // For all practical purposes, it is negligible // and will not be a fairness or security concern. { let j := add(a, shl(5, mod(shr(128, r), n))) n := add(n, w) // `sub(n, 1)`. if iszero(n) { break } let i := add(a, shl(5, n)) let t := mload(i) mstore(i, mload(j)) mstore(j, t) } { let j := add(a, shl(5, mod(and(r, mask), n))) n := add(n, w) // `sub(n, 1)`. if iszero(n) { break } let i := add(a, shl(5, n)) let t := mload(i) mstore(i, mload(j)) mstore(j, t) } } } } } /// @dev Shuffles the bytes in-place with Fisher-Yates shuffle. function shuffle(PRNG memory prng, bytes memory a) internal pure { /// @solidity memory-safe-assembly assembly { let n := mload(a) let w := not(0) let mask := shr(128, w) if n { let b := add(a, 0x01) for { a := add(a, 0x20) } 1 {} { // We can just directly use `keccak256`, cuz // the other approaches don't save much. let r := keccak256(prng, 0x20) mstore(prng, r) // Note that there will be a very tiny modulo bias // if the length of the array is not a power of 2. // For all practical purposes, it is negligible // and will not be a fairness or security concern. { let o := mod(shr(128, r), n) n := add(n, w) // `sub(n, 1)`. if iszero(n) { break } let t := mload(add(b, n)) mstore8(add(a, n), mload(add(b, o))) mstore8(add(a, o), t) } { let o := mod(and(r, mask), n) n := add(n, w) // `sub(n, 1)`. if iszero(n) { break } let t := mload(add(b, n)) mstore8(add(a, n), mload(add(b, o))) mstore8(add(a, o), t) } } } } } } // File: contracts/LibString.sol pragma solidity ^0.8.4; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `length` of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly 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. str := add(mload(0x40), 0x80) // Update the free memory pointer to allocate. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `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) 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 Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory str) { if (value >= 0) { return toString(uint256(value)); } unchecked { str = toString(uint256(-value)); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let length := mload(str) // Load the string length. mstore(str, 0x2d) // Store the '-' character. str := sub(str, 1) // Move back the string pointer by a byte. mstore(str, add(length, 1)) // Update the string length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2 + 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) { str = toHexStringNoPrefix(value, length); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f))) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(str, add(length, length)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(str, start)) { break } } if temp { // Store the function selector of `HexLengthInsufficient()`. mstore(0x00, 0x2194895a) // Revert with (offset, size). revert(0x1c, 0x04) } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. str := add(mload(0x40), 0x80) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory str) { str = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(str, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { str := mload(0x40) // Allocate the memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(str, 0x80)) // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) str := add(str, 2) mstore(str, 40) let o := add(str, 0x20) mstore(add(o, 40), 0) value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory str) { str = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { let length := mload(raw) str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(str, add(length, length)) // Store the length of the output. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let o := add(str, 0x20) let end := add(raw, length) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let mask := shl(7, div(not(0), 255)) result := 1 let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, all indices of the following operations // are byte (ASCII) offsets, not UTF character offsets. /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`. function replace(string memory subject, string memory search, string memory replacement) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) let replacementLength := mload(replacement) subject := add(subject, 0x20) search := add(search, 0x20) replacement := add(replacement, 0x20) result := add(mload(0x40), 0x20) let subjectEnd := add(subject, subjectLength) if iszero(gt(searchLength, subjectLength)) { let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let o := 0 } 1 {} { mstore(add(result, o), mload(add(replacement, o))) o := add(o, 0x20) if iszero(lt(o, replacementLength)) { break } } result := add(result, replacementLength) subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } } let resultRemainder := result result := add(mload(0x40), 0x20) let k := add(sub(resultRemainder, result), sub(subjectEnd, subject)) // Copy the rest of the string one word at a time. for {} lt(subject, subjectEnd) {} { mstore(resultRemainder, mload(subject)) resultRemainder := add(resultRemainder, 0x20) subject := add(subject, 0x20) } result := sub(result, 0x20) let last := add(add(result, 0x20), k) // Zeroize the slot after the string. mstore(last, 0) mstore(0x40, add(last, 0x20)) // Allocate the memory. mstore(result, k) // Store the length. } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for { let subjectLength := mload(subject) } 1 {} { if iszero(mload(search)) { if iszero(gt(from, subjectLength)) { result := from break } result := subjectLength break } let searchLength := mload(search) let subjectStart := add(subject, 0x20) result := not(0) // Initialize to `NOT_FOUND`. subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLength), searchLength), 1) let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(add(search, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLength))) { break } if iszero(lt(searchLength, 0x20)) { for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, searchLength), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = indexOf(subject, search, 0); } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let searchLength := mload(search) if gt(searchLength, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), searchLength) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if eq(keccak256(subject, searchLength), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = lastIndexOf(subject, search, uint256(int256(-1))); } /// @dev Returns whether `subject` starts with `search`. function startsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( iszero(gt(searchLength, mload(subject))), eq( keccak256(add(subject, 0x20), searchLength), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns whether `subject` ends with `search`. function endsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) let subjectLength := mload(subject) // Whether `search` is not longer than `subject`. let withinRange := iszero(gt(searchLength, subjectLength)) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( withinRange, eq( keccak256( // `subject + 0x20 + max(subjectLength - searchLength, 0)`. add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))), searchLength ), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(or(iszero(times), iszero(subjectLength))) { subject := add(subject, 0x20) result := mload(0x40) let output := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let o := 0 } 1 {} { mstore(add(output, o), mload(add(subject, o))) o := add(o, 0x20) if iszero(lt(o, subjectLength)) { break } } output := add(output, subjectLength) times := sub(times, 1) if iszero(times) { break } } mstore(output, 0) // Zeroize the slot after the string. let resultLength := sub(output, add(result, 0x20)) mstore(result, resultLength) // Store the length. // Allocate the memory. mstore(0x40, add(result, add(resultLength, 0x20))) } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(gt(subjectLength, end)) { end := subjectLength } if iszero(gt(subjectLength, start)) { start := subjectLength } if lt(start, end) { result := mload(0x40) let resultLength := sub(end, start) mstore(result, resultLength) subject := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let o := and(add(resultLength, 0x1f), w) } 1 {} { mstore(add(result, o), mload(add(subject, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(result, 0x20), resultLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 0x3f), w))) } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory result) { result = slice(subject, start, uint256(int256(-1))); } /// @dev Returns all the indices of `search` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory search) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) if iszero(gt(searchLength, subjectLength)) { subject := add(subject, 0x20) search := add(search, 0x20) result := add(mload(0x40), 0x20) let subjectStart := subject let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Append to `result`. mstore(result, sub(subject, subjectStart)) result := add(result, 0x20) // Advance `subject` by `searchLength`. subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } let resultEnd := result // Assign `result` to the free memory pointer. result := mload(0x40) // Store the length of `result`. mstore(result, shr(5, sub(resultEnd, add(result, 0x20)))) // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(resultEnd, 0x20)) } } } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) let prevIndex := 0 for {} 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let elementLength := sub(index, prevIndex) mstore(element, elementLength) // Copy the `subject` one word at a time, backwards. for { let o := and(add(elementLength, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(element, 0x20), elementLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(element, and(add(elementLength, 0x3f), w))) // Store the `element` into the array. mstore(indexPtr, element) } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let w := not(0x1f) result := mload(0x40) let aLength := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(mload(a), 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLength := mload(b) let output := add(result, mload(a)) // Copy `b` one word at a time, backwards. for { let o := and(add(bLength, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLength := add(aLength, bLength) let last := add(add(result, 0x20), totalLength) // Zeroize the slot after the string. mstore(last, 0) // Stores the length. mstore(result, totalLength) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 0x1f), w)) } } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let length := mload(subject) if length { result := add(mload(0x40), 0x20) subject := add(subject, 1) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) let w := not(0) for { let o := length } 1 {} { o := add(o, w) let b := and(0xff, mload(add(subject, o))) mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20))) if iszero(o) { break } } result := mload(0x40) mstore(result, length) // Store the length. let last := add(add(result, 0x20), length) mstore(last, 0) // Zeroize the slot after the string. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { for { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) } iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(result, c) result := add(result, 1) continue } let t := shr(248, mload(c)) mstore(result, mload(and(t, 0x1f))) result := add(result, shr(5, t)) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { for { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) } iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(result, c) result := add(result, 1) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), c) result := add(result, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(result, mload(0x19)) // "\\u00XX". result := add(result, 6) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), mload(add(c, 8))) result := add(result, 2) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behaviour is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. result := mload(0x40) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(0x40, add(result, 0x40)) // Zeroize the length slot. mstore(result, 0) // Store the length and bytes. mstore(add(result, 0x1f), packed) // Right pad with zeroes. mstore(add(add(result, 0x20), mload(result)), 0) } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLength := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes of `a` and `b`. or( shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))), mload(sub(add(b, 0x1e), aLength)) ), // `totalLength != 0 && totalLength < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLength, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behaviour is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. resultA := mload(0x40) resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retSize), 0) // Store the return offset. mstore(retStart, 0x20) // End the transaction, returning the string. return(retStart, retSize) } } } // File: contracts/ERC721r.sol pragma solidity ^0.8.17; //import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; //import {ERC721} from "solady/src/tokens/ERC721.sol"; //import {LibPRNG} from "solady/src/utils/LibPRNG.sol"; //import {LibString} from "solady/src/utils/LibString.sol"; abstract contract ERC721r is ERC721 { using LibPRNG for LibPRNG.PRNG; using LibString for uint256; error ContractsCannotMint(); error MustMintAtLeastOneToken(); error NotEnoughAvailableTokens(); string private _name; string private _symbol; mapping(uint256 => uint256) private _availableTokens; uint256 public remainingSupply; uint256 public immutable maxSupply; constructor(string memory name_, string memory symbol_, uint256 maxSupply_) { _name = name_; _symbol = symbol_; maxSupply = maxSupply_; remainingSupply = maxSupply_; } function totalSupply() public view virtual returns (uint256) { return maxSupply - remainingSupply; } function name() public view virtual override returns (string memory) { return _name; } function symbol() public view virtual override returns (string memory) { return _symbol; } function numberMinted(address minter) public view virtual returns (uint32) { return uint32(ERC721._getAux(minter) >> 192); } function _mintRandom(address to, uint256 _numToMint) internal virtual { if (msg.sender != tx.origin) revert ContractsCannotMint(); if (_numToMint == 0) revert MustMintAtLeastOneToken(); if (remainingSupply < _numToMint) revert NotEnoughAvailableTokens(); LibPRNG.PRNG memory prng = LibPRNG.PRNG(uint256(keccak256(abi.encodePacked( block.timestamp, block.prevrandao )))); uint256 updatedRemainingSupply = remainingSupply; for (uint256 i; i < _numToMint; ) { uint256 randomIndex = prng.uniform(updatedRemainingSupply); uint256 tokenId = getAvailableTokenAtIndex(randomIndex, updatedRemainingSupply); _mint(to, tokenId); --updatedRemainingSupply; unchecked {++i;} } _incrementAmountMinted(to, uint32(_numToMint)); remainingSupply = updatedRemainingSupply; } // Must be called in descending order of index function _mintAtIndex(address to, uint256 index) internal virtual { if (msg.sender != tx.origin) revert ContractsCannotMint(); if (remainingSupply == 0) revert NotEnoughAvailableTokens(); uint256 tokenId = getAvailableTokenAtIndex(index, remainingSupply); --remainingSupply; _incrementAmountMinted(to, 1); _mint(to, tokenId); } // Implements https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle. Code taken from CryptoPhunksV2 function getAvailableTokenAtIndex(uint256 indexToUse, uint256 updatedNumAvailableTokens) private returns (uint256 result) { uint256 valAtIndex = _availableTokens[indexToUse]; uint256 lastIndex = updatedNumAvailableTokens - 1; uint256 lastValInArray = _availableTokens[lastIndex]; result = valAtIndex == 0 ? indexToUse : valAtIndex; if (indexToUse != lastIndex) { _availableTokens[indexToUse] = lastValInArray == 0 ? lastIndex : lastValInArray; } if (lastValInArray != 0) { delete _availableTokens[lastIndex]; } } function _setExtraAddressData(address minter, uint192 extraData) internal virtual { uint32 numMinted = numberMinted(minter); ERC721._setAux( minter, uint224((uint256(numMinted) << 192)) | uint224(extraData) ); } function _getAddressExtraData(address minter) internal view virtual returns (uint192) { return uint192(_getAux(minter)); } function _incrementAmountMinted(address minter, uint32 newMints) private { uint32 numMinted = numberMinted(minter); uint32 newMintNumMinted = numMinted + uint32(newMints); uint224 auxData = ERC721._getAux(minter); ERC721._setAux( minter, uint224(uint256(newMintNumMinted) << 192) | uint224(uint192(auxData)) ); } } // File: contracts/MetaLifeResidence.sol pragma solidity 0.8.23; contract MetaLifeResidence is ReentrancyGuard, Ownable, ERC721r { using Strings for uint256; string public baseURI; address public originOwner = 0x4aBd9bd6f92654b45C42A9e0f9a3D23C7c14406e; address payable public collector; struct Eligibility { uint8 total; uint8 claimed; } mapping(address => Eligibility) public allowlist; event Minted(address indexed from, uint256 timestamp); constructor() ERC721r('Meta-Life Residence', 'MLR', 7_00) Ownable(originOwner){} function withdrawAll() public payable onlyOwner { collector.transfer(address(this).balance); } function setCollector(address payable _newCollector) public onlyOwner { collector = _newCollector; } function _setBaseURI(string memory _newBaseURI) public onlyOwner { baseURI = _newBaseURI; } function _baseURI() internal view virtual returns (string memory) { return baseURI; } function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), 'unknow token'); string memory uri = _baseURI(); return bytes(uri).length > 0 ? string(abi.encodePacked(uri, tokenId.toString())) : ""; } function tokenExist(uint256 tokenId) public view returns(bool) { return _exists(tokenId); } function remaining(address wallet) public view virtual returns (uint8) { return allowlist[wallet].total - allowlist[wallet].claimed; } function addAllowlist(address[] calldata _toAddAddresses, uint8[] calldata _quantities) external onlyOwner { require(_toAddAddresses.length == _quantities.length, 'Nb address and nb quantities must be equal'); for (uint i = 0; i < _toAddAddresses.length; i++) { allowlist[_toAddAddresses[i]].total += _quantities[i]; } } function removeAllowlist(address[] calldata _addresses, uint8[] calldata _quantities) external onlyOwner { require(_addresses.length == _quantities.length, 'Nb address and nb quantities must be equal'); for (uint i = 0; i < _addresses.length; i++) { if (remaining(_addresses[i]) - _quantities[i] >= 0) { allowlist[_addresses[i]].total -= _quantities[i]; } } } function mintRandom(uint8 _quantities) external { require(remaining(msg.sender) > 0, "Not eligible"); require(remaining(msg.sender) >= _quantities, "Not enough claimable tokens"); require(maxSupply >= totalSupply() + _quantities, "Supply limit exceed"); allowlist[msg.sender].claimed += _quantities; _mintRandom(msg.sender, _quantities); emit Minted(msg.sender, block.timestamp); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountBalanceOverflow","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"ContractsCannotMint","type":"error"},{"inputs":[],"name":"MustMintAtLeastOneToken","type":"error"},{"inputs":[],"name":"NotEnoughAvailableTokens","type":"error"},{"inputs":[],"name":"NotOwnerNorApproved","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":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":"isApproved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Minted","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"_setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_toAddAddresses","type":"address[]"},{"internalType":"uint8[]","name":"_quantities","type":"uint8[]"}],"name":"addAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowlist","outputs":[{"internalType":"uint8","name":"total","type":"uint8"},{"internalType":"uint8","name":"claimed","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collector","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"result","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":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_quantities","type":"uint8"}],"name":"mintRandom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"originOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"remaining","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remainingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint8[]","name":"_quantities","type":"uint8[]"}],"name":"removeAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"id","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":"isApproved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newCollector","type":"address"}],"name":"setCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"result","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":"tokenExist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"withdrawAll","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a0604052734abd9bd6f92654b45c42a9e0f9a3d23c7c14406e60075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801562000064575f80fd5b506040518060400160405280601381526020017f4d6574612d4c696665205265736964656e6365000000000000000000000000008152506040518060400160405280600381526020017f4d4c5200000000000000000000000000000000000000000000000000000000008152506102bc60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660015f819055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000170575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620001679190620002c4565b60405180910390fd5b6200018181620001be60201b60201c565b50826002908162000193919062000543565b508160039081620001a5919062000543565b5080608081815250508060058190555050505062000627565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620002ac8262000281565b9050919050565b620002be81620002a0565b82525050565b5f602082019050620002d95f830184620002b3565b92915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200035b57607f821691505b60208210810362000371576200037062000316565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003d57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000398565b620003e1868362000398565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200042b620004256200041f84620003f9565b62000402565b620003f9565b9050919050565b5f819050919050565b62000446836200040b565b6200045e620004558262000432565b848454620003a4565b825550505050565b5f90565b6200047462000466565b620004818184846200043b565b505050565b5b81811015620004a8576200049c5f826200046a565b60018101905062000487565b5050565b601f821115620004f757620004c18162000377565b620004cc8462000389565b81016020851015620004dc578190505b620004f4620004eb8562000389565b83018262000486565b50505b505050565b5f82821c905092915050565b5f620005195f1984600802620004fc565b1980831691505092915050565b5f62000533838362000508565b9150826002028217905092915050565b6200054e82620002df565b67ffffffffffffffff8111156200056a5762000569620002e9565b5b62000576825462000343565b62000583828285620004ac565b5f60209050601f831160018114620005b9575f8415620005a4578287015190505b620005b0858262000526565b8655506200061f565b601f198416620005c98662000377565b5f5b82811015620005f257848901518255600182019150602085019450602081019050620005cb565b868310156200061257848901516200060e601f89168262000508565b8355505b6001600288020188555050505b505050505050565b608051612f256200064e5f395f818161088001528181610ac501526113d00152612f255ff3fe6080604052600436106101e2575f3560e01c8063853828b611610101578063c87b56dd11610094578063dc33e68111610063578063dc33e68114610699578063e985e9c5146106d5578063f2fde38b14610711578063fb5b82d014610739576101e2565b8063c87b56dd146105cd578063cc0c523614610609578063d5abeb0114610645578063da0239a61461066f576101e2565b8063a22cb465116100d0578063a22cb46514610510578063a7cd52cb14610538578063b399b0bc14610575578063b88d4fde146105b1576101e2565b8063853828b6146104885780638da5cb5b14610492578063913e77ad146104bc57806395d89b41146104e6576101e2565b806331b5b907116101795780636352211e116101485780636352211e146103d05780636c0360eb1461040c57806370a0823114610436578063715018a614610472576101e2565b806331b5b9071461033c5780633fb580f71461036457806342842e0e1461038c578063594bf62b146103a8576101e2565b806318160ddd116101b557806318160ddd146102a457806323b872dd146102ce578063282e7811146102ea5780632db5b8e714610314576101e2565b806301ffc9a7146101e657806306fdde0314610222578063081812fc1461024c578063095ea7b314610288575b5f80fd5b3480156101f1575f80fd5b5061020c60048036038101906102079190611f3d565b610761565b6040516102199190611f82565b60405180910390f35b34801561022d575f80fd5b50610236610785565b6040516102439190612025565b60405180910390f35b348015610257575f80fd5b50610272600480360381019061026d9190612078565b610815565b60405161027f91906120e2565b60405180910390f35b6102a2600480360381019061029d9190612125565b61086b565b005b3480156102af575f80fd5b506102b861087a565b6040516102c59190612172565b60405180910390f35b6102e860048036038101906102e3919061218b565b6108ae565b005b3480156102f5575f80fd5b506102fe6109ea565b60405161030b91906120e2565b60405180910390f35b34801561031f575f80fd5b5061033a60048036038101906103359190612211565b610a0f565b005b348015610347575f80fd5b50610362600480360381019061035d9190612368565b610bf6565b005b34801561036f575f80fd5b5061038a60048036038101906103859190612461565b610c11565b005b6103a660048036038101906103a1919061218b565b610d42565b005b3480156103b3575f80fd5b506103ce60048036038101906103c99190612461565b610d7b565b005b3480156103db575f80fd5b506103f660048036038101906103f19190612078565b610f18565b60405161040391906120e2565b60405180910390f35b348015610417575f80fd5b50610420610f3b565b60405161042d9190612025565b60405180910390f35b348015610441575f80fd5b5061045c600480360381019061045791906124df565b610fc7565b6040516104699190612172565b60405180910390f35b34801561047d575f80fd5b50610486611014565b005b610490611027565b005b34801561049d575f80fd5b506104a6611096565b6040516104b391906120e2565b60405180910390f35b3480156104c7575f80fd5b506104d06110be565b6040516104dd919061252a565b60405180910390f35b3480156104f1575f80fd5b506104fa6110e3565b6040516105079190612025565b60405180910390f35b34801561051b575f80fd5b506105366004803603810190610531919061256d565b611173565b005b348015610543575f80fd5b5061055e600480360381019061055991906124df565b6111c6565b60405161056c9291906125ba565b60405180910390f35b348015610580575f80fd5b5061059b600480360381019061059691906124df565b6111fe565b6040516105a891906125e1565b60405180910390f35b6105cb60048036038101906105c6919061264f565b6112a9565b005b3480156105d8575f80fd5b506105f360048036038101906105ee9190612078565b611319565b6040516106009190612025565b60405180910390f35b348015610614575f80fd5b5061062f600480360381019061062a9190612078565b6113bd565b60405161063c9190611f82565b60405180910390f35b348015610650575f80fd5b506106596113ce565b6040516106669190612172565b60405180910390f35b34801561067a575f80fd5b506106836113f2565b6040516106909190612172565b60405180910390f35b3480156106a4575f80fd5b506106bf60048036038101906106ba91906124df565b6113f8565b6040516106cc91906126f1565b60405180910390f35b3480156106e0575f80fd5b506106fb60048036038101906106f6919061270a565b61142b565b6040516107089190611f82565b60405180910390f35b34801561071c575f80fd5b50610737600480360381019061073291906124df565b61144d565b005b348015610744575f80fd5b5061075f600480360381019061075a9190612772565b6114d1565b005b5f8160e01c635b5e139f81146380ac58cd82146301ffc9a783141717915050919050565b606060028054610794906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546107c0906127ca565b801561080b5780601f106107e25761010080835404028352916020019161080b565b820191905f5260205f20905b8154815290600101906020018083116107ee57829003601f168201915b5050505050905090565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f2082018201805460601b60601c61085e5763ceea21b65f526004601cfd5b8060010154915050919050565b61087633838361151c565b5050565b5f6005547f00000000000000000000000000000000000000000000000000000000000000006108a99190612827565b905090565b6108b98383836115cc565b5f1960601c83811693508281169250815f52337f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f20820182018054808316868114810261092657806109195763ceea21b65f526004601cfd5b63a11481005f526004601cfd5b856109385763ea553b345f526004601cfd5b865f52826001015480331488331417610963576030600c205461096257634b6e7f185f526004601cfd5b5b8015610970575f84600101555b5085871882188355601c600c206001815403815550855f52601c600c20600181540163ffffffff81166109aa576301336cea5f526004601cfd5b80825550508486887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4505050506109e58383836115d1565b505050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610a19336111fe565b60ff1611610a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a53906128a4565b60405180910390fd5b8060ff16610a69336111fe565b60ff161015610aad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa49061290c565b60405180910390fd5b8060ff16610ab961087a565b610ac3919061292a565b7f00000000000000000000000000000000000000000000000000000000000000001015610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c906129a7565b60405180910390fd5b8060095f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160018282829054906101000a900460ff16610b8091906129c5565b92506101000a81548160ff021916908360ff160217905550610ba5338260ff166115d6565b3373ffffffffffffffffffffffffffffffffffffffff167f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe42604051610beb9190612172565b60405180910390a250565b610bfe61175a565b8060069081610c0d9190612b96565b5050565b610c1961175a565b818190508484905014610c61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c5890612cd5565b60405180910390fd5b5f5b84849050811015610d3b57828282818110610c8157610c80612cf3565b5b9050602002016020810190610c969190612211565b60095f878785818110610cac57610cab612cf3565b5b9050602002016020810190610cc191906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610d1691906129c5565b92506101000a81548160ff021916908360ff1602179055508080600101915050610c63565b5050505050565b610d4d8383836108ae565b610d56826117e1565b15610d7657610d7583838360405180602001604052805f8152506117eb565b5b505050565b610d8361175a565b818190508484905014610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc290612cd5565b60405180910390fd5b5f5b84849050811015610f11575f838383818110610dec57610deb612cf3565b5b9050602002016020810190610e019190612211565b610e31878785818110610e1757610e16612cf3565b5b9050602002016020810190610e2c91906124df565b6111fe565b610e3b9190612d20565b60ff1610610f0457828282818110610e5657610e55612cf3565b5b9050602002016020810190610e6b9190612211565b60095f878785818110610e8157610e80612cf3565b5b9050602002016020810190610e9691906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610eeb9190612d20565b92506101000a81548160ff021916908360ff1602179055505b8080600101915050610dcd565b5050505050565b5f610f2282611878565b905080610f365763ceea21b65f526004601cfd5b919050565b60068054610f48906127ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610f74906127ca565b8015610fbf5780601f10610f9657610100808354040283529160200191610fbf565b820191905f5260205f20905b815481529060010190602001808311610fa257829003601f168201915b505050505081565b5f81610fda57638f4eb6045f526004601cfd5b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f5263ffffffff601c600c2054169050919050565b61101c61175a565b6110255f6118b6565b565b61102f61175a565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015611093573d5f803e3d5ffd5b50565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600380546110f2906127ca565b80601f016020809104026020016040519081016040528092919081815260200182805461111e906127ca565b80156111695780601f1061114057610100808354040283529160200191611169565b820191905f5260205f20905b81548152906001019060200180831161114c57829003601f168201915b5050505050905090565b801515905081601c52670a5a2e7a00000000600852335f52806030600c2055805f528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa35050565b6009602052805f5260405f205f91509050805f015f9054906101000a900460ff1690805f0160019054906101000a900460ff16905082565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160019054906101000a900460ff1660095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f9054906101000a900460ff166112a29190612d20565b9050919050565b6112b48585856108ae565b6112bd846117e1565b156113125761131185858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050506117eb565b5b5050505050565b606061132482611979565b611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135a90612d9e565b60405180910390fd5b5f61136c6119b4565b90505f81511161138a5760405180602001604052805f8152506113b5565b8061139484611a44565b6040516020016113a5929190612df6565b6040516020818303038152906040525b915050919050565b5f6113c782611979565b9050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055481565b5f60c061140483611b0e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16901c9050919050565b5f81601c52670a5a2e7a00000000600852825f526030600c2054905092915050565b61145561175a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114c5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016114bc91906120e2565b60405180910390fd5b6114ce816118b6565b50565b6114d961175a565b8060085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f1960601c82811692508381169350815f52837f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f208201820180548216806115725763ceea21b65f526004601cfd5b80861486151761159757805f526030600c205461159657634b6e7f185f526004601cfd5b5b8482600101558385827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4505050505050565b505050565b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461163b576040517fd9d552c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8103611674576040517f4600cfe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060055410156116b0576040517f7775abdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051806020016040528042446040516020016116cf929190612e39565b604051602081830303815290604052805190602001205f1c81525090505f60055490505f5b83811015611742575f6117108385611b4690919063ffffffff16565b90505f61171d8285611b6f565b90506117298782611c0c565b8361173390612e64565b935082600101925050506116f4565b5061174d8484611ce0565b8060058190555050505050565b611762611d3e565b73ffffffffffffffffffffffffffffffffffffffff16611780611096565b73ffffffffffffffffffffffffffffffffffffffff16146117df576117a3611d3e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016117d691906120e2565b60405180910390fd5b565b5f813b9050919050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015611832578060c08401826020870160045afa505b60208360a48301601c86015f8a5af1611857573d15611853573d5f803e3d5ffd5b5f83525b8160e01b83511461186f5763d1a57ed65f526004601cfd5b50505050505050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b60601c9050919050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b9050919050565b6060600680546119c3906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546119ef906127ca565b8015611a3a5780601f10611a1157610100808354040283529160200191611a3a565b820191905f5260205f20905b815481529060010190602001808311611a1d57829003601f168201915b5050505050905090565b60605f6001611a5284611d45565b0190505f8167ffffffffffffffff811115611a7057611a6f612244565b5b6040519080825280601f01601f191660200182016040528015611aa25781602001600182028036833780820191505090505b5090505f82602001820190505b600115611b03578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611af857611af7612e8b565b5b0494505f8503611aaf575b819350505050919050565b5f7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c205460201c9050919050565b5f5b600115611b645760208320905080835281825f03068110611b48575b818106905092915050565b5f8060045f8581526020019081526020015f205490505f600184611b939190612827565b90505f60045f8381526020019081526020015f205490505f8314611bb75782611bb9565b855b9350818614611be7575f8114611bcf5780611bd1565b815b60045f8881526020019081526020015f20819055505b5f8114611c035760045f8381526020019081526020015f205f90555b50505092915050565b611c175f83836115cc565b8160601b60601c915081611c325763ea553b345f526004601cfd5b805f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f208101810180548060601b15611c795763c991cbb15f526004601cfd5b8381178255835f52601c600c20600181540163ffffffff8116611ca3576301336cea5f526004601cfd5b808255505082845f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a45050611cdc5f83836115d1565b5050565b5f611cea836113f8565b90505f8282611cf99190612eb8565b90505f611d0585611b0e565b9050611d37858277ffffffffffffffffffffffffffffffffffffffffffffffff1660c08563ffffffff16901b17611e96565b5050505050565b5f33905090565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611da1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611d9757611d96612e8b565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611dde576d04ee2d6d415b85acef81000000008381611dd457611dd3612e8b565b5b0492506020810190505b662386f26fc100008310611e0d57662386f26fc100008381611e0357611e02612e8b565b5b0492506010810190505b6305f5e1008310611e36576305f5e1008381611e2c57611e2b612e8b565b5b0492506008810190505b6127108310611e5b576127108381611e5157611e50612e8b565b5b0492506004810190505b60648310611e7e5760648381611e7457611e73612e8b565b5b0492506002810190505b600a8310611e8d576001810190505b80915050919050565b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c2080548060201c831860201b8118825550505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611f1c81611ee8565b8114611f26575f80fd5b50565b5f81359050611f3781611f13565b92915050565b5f60208284031215611f5257611f51611ee0565b5b5f611f5f84828501611f29565b91505092915050565b5f8115159050919050565b611f7c81611f68565b82525050565b5f602082019050611f955f830184611f73565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611fd2578082015181840152602081019050611fb7565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611ff782611f9b565b6120018185611fa5565b9350612011818560208601611fb5565b61201a81611fdd565b840191505092915050565b5f6020820190508181035f83015261203d8184611fed565b905092915050565b5f819050919050565b61205781612045565b8114612061575f80fd5b50565b5f813590506120728161204e565b92915050565b5f6020828403121561208d5761208c611ee0565b5b5f61209a84828501612064565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6120cc826120a3565b9050919050565b6120dc816120c2565b82525050565b5f6020820190506120f55f8301846120d3565b92915050565b612104816120c2565b811461210e575f80fd5b50565b5f8135905061211f816120fb565b92915050565b5f806040838503121561213b5761213a611ee0565b5b5f61214885828601612111565b925050602061215985828601612064565b9150509250929050565b61216c81612045565b82525050565b5f6020820190506121855f830184612163565b92915050565b5f805f606084860312156121a2576121a1611ee0565b5b5f6121af86828701612111565b93505060206121c086828701612111565b92505060406121d186828701612064565b9150509250925092565b5f60ff82169050919050565b6121f0816121db565b81146121fa575f80fd5b50565b5f8135905061220b816121e7565b92915050565b5f6020828403121561222657612225611ee0565b5b5f612233848285016121fd565b91505092915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61227a82611fdd565b810181811067ffffffffffffffff8211171561229957612298612244565b5b80604052505050565b5f6122ab611ed7565b90506122b78282612271565b919050565b5f67ffffffffffffffff8211156122d6576122d5612244565b5b6122df82611fdd565b9050602081019050919050565b828183375f83830152505050565b5f61230c612307846122bc565b6122a2565b90508281526020810184848401111561232857612327612240565b5b6123338482856122ec565b509392505050565b5f82601f83011261234f5761234e61223c565b5b813561235f8482602086016122fa565b91505092915050565b5f6020828403121561237d5761237c611ee0565b5b5f82013567ffffffffffffffff81111561239a57612399611ee4565b5b6123a68482850161233b565b91505092915050565b5f80fd5b5f80fd5b5f8083601f8401126123cc576123cb61223c565b5b8235905067ffffffffffffffff8111156123e9576123e86123af565b5b602083019150836020820283011115612405576124046123b3565b5b9250929050565b5f8083601f8401126124215761242061223c565b5b8235905067ffffffffffffffff81111561243e5761243d6123af565b5b60208301915083602082028301111561245a576124596123b3565b5b9250929050565b5f805f806040858703121561247957612478611ee0565b5b5f85013567ffffffffffffffff81111561249657612495611ee4565b5b6124a2878288016123b7565b9450945050602085013567ffffffffffffffff8111156124c5576124c4611ee4565b5b6124d18782880161240c565b925092505092959194509250565b5f602082840312156124f4576124f3611ee0565b5b5f61250184828501612111565b91505092915050565b5f612514826120a3565b9050919050565b6125248161250a565b82525050565b5f60208201905061253d5f83018461251b565b92915050565b61254c81611f68565b8114612556575f80fd5b50565b5f8135905061256781612543565b92915050565b5f806040838503121561258357612582611ee0565b5b5f61259085828601612111565b92505060206125a185828601612559565b9150509250929050565b6125b4816121db565b82525050565b5f6040820190506125cd5f8301856125ab565b6125da60208301846125ab565b9392505050565b5f6020820190506125f45f8301846125ab565b92915050565b5f8083601f84011261260f5761260e61223c565b5b8235905067ffffffffffffffff81111561262c5761262b6123af565b5b602083019150836001820283011115612648576126476123b3565b5b9250929050565b5f805f805f6080868803121561266857612667611ee0565b5b5f61267588828901612111565b955050602061268688828901612111565b945050604061269788828901612064565b935050606086013567ffffffffffffffff8111156126b8576126b7611ee4565b5b6126c4888289016125fa565b92509250509295509295909350565b5f63ffffffff82169050919050565b6126eb816126d3565b82525050565b5f6020820190506127045f8301846126e2565b92915050565b5f80604083850312156127205761271f611ee0565b5b5f61272d85828601612111565b925050602061273e85828601612111565b9150509250929050565b6127518161250a565b811461275b575f80fd5b50565b5f8135905061276c81612748565b92915050565b5f6020828403121561278757612786611ee0565b5b5f6127948482850161275e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806127e157607f821691505b6020821081036127f4576127f361279d565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61283182612045565b915061283c83612045565b9250828203905081811115612854576128536127fa565b5b92915050565b7f4e6f7420656c696769626c6500000000000000000000000000000000000000005f82015250565b5f61288e600c83611fa5565b91506128998261285a565b602082019050919050565b5f6020820190508181035f8301526128bb81612882565b9050919050565b7f4e6f7420656e6f75676820636c61696d61626c6520746f6b656e7300000000005f82015250565b5f6128f6601b83611fa5565b9150612901826128c2565b602082019050919050565b5f6020820190508181035f830152612923816128ea565b9050919050565b5f61293482612045565b915061293f83612045565b9250828201905080821115612957576129566127fa565b5b92915050565b7f537570706c79206c696d697420657863656564000000000000000000000000005f82015250565b5f612991601383611fa5565b915061299c8261295d565b602082019050919050565b5f6020820190508181035f8301526129be81612985565b9050919050565b5f6129cf826121db565b91506129da836121db565b9250828201905060ff8111156129f3576129f26127fa565b5b92915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302612a557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612a1a565b612a5f8683612a1a565b95508019841693508086168417925050509392505050565b5f819050919050565b5f612a9a612a95612a9084612045565b612a77565b612045565b9050919050565b5f819050919050565b612ab383612a80565b612ac7612abf82612aa1565b848454612a26565b825550505050565b5f90565b612adb612acf565b612ae6818484612aaa565b505050565b5b81811015612b0957612afe5f82612ad3565b600181019050612aec565b5050565b601f821115612b4e57612b1f816129f9565b612b2884612a0b565b81016020851015612b37578190505b612b4b612b4385612a0b565b830182612aeb565b50505b505050565b5f82821c905092915050565b5f612b6e5f1984600802612b53565b1980831691505092915050565b5f612b868383612b5f565b9150826002028217905092915050565b612b9f82611f9b565b67ffffffffffffffff811115612bb857612bb7612244565b5b612bc282546127ca565b612bcd828285612b0d565b5f60209050601f831160018114612bfe575f8415612bec578287015190505b612bf68582612b7b565b865550612c5d565b601f198416612c0c866129f9565b5f5b82811015612c3357848901518255600182019150602085019450602081019050612c0e565b86831015612c505784890151612c4c601f891682612b5f565b8355505b6001600288020188555050505b505050505050565b7f4e62206164647265737320616e64206e62207175616e746974696573206d75735f8201527f7420626520657175616c00000000000000000000000000000000000000000000602082015250565b5f612cbf602a83611fa5565b9150612cca82612c65565b604082019050919050565b5f6020820190508181035f830152612cec81612cb3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612d2a826121db565b9150612d35836121db565b9250828203905060ff811115612d4e57612d4d6127fa565b5b92915050565b7f756e6b6e6f7720746f6b656e00000000000000000000000000000000000000005f82015250565b5f612d88600c83611fa5565b9150612d9382612d54565b602082019050919050565b5f6020820190508181035f830152612db581612d7c565b9050919050565b5f81905092915050565b5f612dd082611f9b565b612dda8185612dbc565b9350612dea818560208601611fb5565b80840191505092915050565b5f612e018285612dc6565b9150612e0d8284612dc6565b91508190509392505050565b5f819050919050565b612e33612e2e82612045565b612e19565b82525050565b5f612e448285612e22565b602082019150612e548284612e22565b6020820191508190509392505050565b5f612e6e82612045565b91505f8203612e8057612e7f6127fa565b5b600182039050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612ec2826126d3565b9150612ecd836126d3565b9250828201905063ffffffff811115612ee957612ee86127fa565b5b9291505056fea2646970667358221220b759f54012460361b42f3a4227bec927bf17ab62cd396622764adcd08386126364736f6c63430008170033
Deployed Bytecode
0x6080604052600436106101e2575f3560e01c8063853828b611610101578063c87b56dd11610094578063dc33e68111610063578063dc33e68114610699578063e985e9c5146106d5578063f2fde38b14610711578063fb5b82d014610739576101e2565b8063c87b56dd146105cd578063cc0c523614610609578063d5abeb0114610645578063da0239a61461066f576101e2565b8063a22cb465116100d0578063a22cb46514610510578063a7cd52cb14610538578063b399b0bc14610575578063b88d4fde146105b1576101e2565b8063853828b6146104885780638da5cb5b14610492578063913e77ad146104bc57806395d89b41146104e6576101e2565b806331b5b907116101795780636352211e116101485780636352211e146103d05780636c0360eb1461040c57806370a0823114610436578063715018a614610472576101e2565b806331b5b9071461033c5780633fb580f71461036457806342842e0e1461038c578063594bf62b146103a8576101e2565b806318160ddd116101b557806318160ddd146102a457806323b872dd146102ce578063282e7811146102ea5780632db5b8e714610314576101e2565b806301ffc9a7146101e657806306fdde0314610222578063081812fc1461024c578063095ea7b314610288575b5f80fd5b3480156101f1575f80fd5b5061020c60048036038101906102079190611f3d565b610761565b6040516102199190611f82565b60405180910390f35b34801561022d575f80fd5b50610236610785565b6040516102439190612025565b60405180910390f35b348015610257575f80fd5b50610272600480360381019061026d9190612078565b610815565b60405161027f91906120e2565b60405180910390f35b6102a2600480360381019061029d9190612125565b61086b565b005b3480156102af575f80fd5b506102b861087a565b6040516102c59190612172565b60405180910390f35b6102e860048036038101906102e3919061218b565b6108ae565b005b3480156102f5575f80fd5b506102fe6109ea565b60405161030b91906120e2565b60405180910390f35b34801561031f575f80fd5b5061033a60048036038101906103359190612211565b610a0f565b005b348015610347575f80fd5b50610362600480360381019061035d9190612368565b610bf6565b005b34801561036f575f80fd5b5061038a60048036038101906103859190612461565b610c11565b005b6103a660048036038101906103a1919061218b565b610d42565b005b3480156103b3575f80fd5b506103ce60048036038101906103c99190612461565b610d7b565b005b3480156103db575f80fd5b506103f660048036038101906103f19190612078565b610f18565b60405161040391906120e2565b60405180910390f35b348015610417575f80fd5b50610420610f3b565b60405161042d9190612025565b60405180910390f35b348015610441575f80fd5b5061045c600480360381019061045791906124df565b610fc7565b6040516104699190612172565b60405180910390f35b34801561047d575f80fd5b50610486611014565b005b610490611027565b005b34801561049d575f80fd5b506104a6611096565b6040516104b391906120e2565b60405180910390f35b3480156104c7575f80fd5b506104d06110be565b6040516104dd919061252a565b60405180910390f35b3480156104f1575f80fd5b506104fa6110e3565b6040516105079190612025565b60405180910390f35b34801561051b575f80fd5b506105366004803603810190610531919061256d565b611173565b005b348015610543575f80fd5b5061055e600480360381019061055991906124df565b6111c6565b60405161056c9291906125ba565b60405180910390f35b348015610580575f80fd5b5061059b600480360381019061059691906124df565b6111fe565b6040516105a891906125e1565b60405180910390f35b6105cb60048036038101906105c6919061264f565b6112a9565b005b3480156105d8575f80fd5b506105f360048036038101906105ee9190612078565b611319565b6040516106009190612025565b60405180910390f35b348015610614575f80fd5b5061062f600480360381019061062a9190612078565b6113bd565b60405161063c9190611f82565b60405180910390f35b348015610650575f80fd5b506106596113ce565b6040516106669190612172565b60405180910390f35b34801561067a575f80fd5b506106836113f2565b6040516106909190612172565b60405180910390f35b3480156106a4575f80fd5b506106bf60048036038101906106ba91906124df565b6113f8565b6040516106cc91906126f1565b60405180910390f35b3480156106e0575f80fd5b506106fb60048036038101906106f6919061270a565b61142b565b6040516107089190611f82565b60405180910390f35b34801561071c575f80fd5b50610737600480360381019061073291906124df565b61144d565b005b348015610744575f80fd5b5061075f600480360381019061075a9190612772565b6114d1565b005b5f8160e01c635b5e139f81146380ac58cd82146301ffc9a783141717915050919050565b606060028054610794906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546107c0906127ca565b801561080b5780601f106107e25761010080835404028352916020019161080b565b820191905f5260205f20905b8154815290600101906020018083116107ee57829003601f168201915b5050505050905090565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f2082018201805460601b60601c61085e5763ceea21b65f526004601cfd5b8060010154915050919050565b61087633838361151c565b5050565b5f6005547f00000000000000000000000000000000000000000000000000000000000002bc6108a99190612827565b905090565b6108b98383836115cc565b5f1960601c83811693508281169250815f52337f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f20820182018054808316868114810261092657806109195763ceea21b65f526004601cfd5b63a11481005f526004601cfd5b856109385763ea553b345f526004601cfd5b865f52826001015480331488331417610963576030600c205461096257634b6e7f185f526004601cfd5b5b8015610970575f84600101555b5085871882188355601c600c206001815403815550855f52601c600c20600181540163ffffffff81166109aa576301336cea5f526004601cfd5b80825550508486887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4505050506109e58383836115d1565b505050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610a19336111fe565b60ff1611610a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a53906128a4565b60405180910390fd5b8060ff16610a69336111fe565b60ff161015610aad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa49061290c565b60405180910390fd5b8060ff16610ab961087a565b610ac3919061292a565b7f00000000000000000000000000000000000000000000000000000000000002bc1015610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c906129a7565b60405180910390fd5b8060095f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160018282829054906101000a900460ff16610b8091906129c5565b92506101000a81548160ff021916908360ff160217905550610ba5338260ff166115d6565b3373ffffffffffffffffffffffffffffffffffffffff167f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe42604051610beb9190612172565b60405180910390a250565b610bfe61175a565b8060069081610c0d9190612b96565b5050565b610c1961175a565b818190508484905014610c61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c5890612cd5565b60405180910390fd5b5f5b84849050811015610d3b57828282818110610c8157610c80612cf3565b5b9050602002016020810190610c969190612211565b60095f878785818110610cac57610cab612cf3565b5b9050602002016020810190610cc191906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610d1691906129c5565b92506101000a81548160ff021916908360ff1602179055508080600101915050610c63565b5050505050565b610d4d8383836108ae565b610d56826117e1565b15610d7657610d7583838360405180602001604052805f8152506117eb565b5b505050565b610d8361175a565b818190508484905014610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc290612cd5565b60405180910390fd5b5f5b84849050811015610f11575f838383818110610dec57610deb612cf3565b5b9050602002016020810190610e019190612211565b610e31878785818110610e1757610e16612cf3565b5b9050602002016020810190610e2c91906124df565b6111fe565b610e3b9190612d20565b60ff1610610f0457828282818110610e5657610e55612cf3565b5b9050602002016020810190610e6b9190612211565b60095f878785818110610e8157610e80612cf3565b5b9050602002016020810190610e9691906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610eeb9190612d20565b92506101000a81548160ff021916908360ff1602179055505b8080600101915050610dcd565b5050505050565b5f610f2282611878565b905080610f365763ceea21b65f526004601cfd5b919050565b60068054610f48906127ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610f74906127ca565b8015610fbf5780601f10610f9657610100808354040283529160200191610fbf565b820191905f5260205f20905b815481529060010190602001808311610fa257829003601f168201915b505050505081565b5f81610fda57638f4eb6045f526004601cfd5b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f5263ffffffff601c600c2054169050919050565b61101c61175a565b6110255f6118b6565b565b61102f61175a565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015611093573d5f803e3d5ffd5b50565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600380546110f2906127ca565b80601f016020809104026020016040519081016040528092919081815260200182805461111e906127ca565b80156111695780601f1061114057610100808354040283529160200191611169565b820191905f5260205f20905b81548152906001019060200180831161114c57829003601f168201915b5050505050905090565b801515905081601c52670a5a2e7a00000000600852335f52806030600c2055805f528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa35050565b6009602052805f5260405f205f91509050805f015f9054906101000a900460ff1690805f0160019054906101000a900460ff16905082565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160019054906101000a900460ff1660095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f9054906101000a900460ff166112a29190612d20565b9050919050565b6112b48585856108ae565b6112bd846117e1565b156113125761131185858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050506117eb565b5b5050505050565b606061132482611979565b611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135a90612d9e565b60405180910390fd5b5f61136c6119b4565b90505f81511161138a5760405180602001604052805f8152506113b5565b8061139484611a44565b6040516020016113a5929190612df6565b6040516020818303038152906040525b915050919050565b5f6113c782611979565b9050919050565b7f00000000000000000000000000000000000000000000000000000000000002bc81565b60055481565b5f60c061140483611b0e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16901c9050919050565b5f81601c52670a5a2e7a00000000600852825f526030600c2054905092915050565b61145561175a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114c5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016114bc91906120e2565b60405180910390fd5b6114ce816118b6565b50565b6114d961175a565b8060085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f1960601c82811692508381169350815f52837f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f208201820180548216806115725763ceea21b65f526004601cfd5b80861486151761159757805f526030600c205461159657634b6e7f185f526004601cfd5b5b8482600101558385827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4505050505050565b505050565b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461163b576040517fd9d552c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8103611674576040517f4600cfe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060055410156116b0576040517f7775abdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051806020016040528042446040516020016116cf929190612e39565b604051602081830303815290604052805190602001205f1c81525090505f60055490505f5b83811015611742575f6117108385611b4690919063ffffffff16565b90505f61171d8285611b6f565b90506117298782611c0c565b8361173390612e64565b935082600101925050506116f4565b5061174d8484611ce0565b8060058190555050505050565b611762611d3e565b73ffffffffffffffffffffffffffffffffffffffff16611780611096565b73ffffffffffffffffffffffffffffffffffffffff16146117df576117a3611d3e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016117d691906120e2565b60405180910390fd5b565b5f813b9050919050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015611832578060c08401826020870160045afa505b60208360a48301601c86015f8a5af1611857573d15611853573d5f803e3d5ffd5b5f83525b8160e01b83511461186f5763d1a57ed65f526004601cfd5b50505050505050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b60601c9050919050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b9050919050565b6060600680546119c3906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546119ef906127ca565b8015611a3a5780601f10611a1157610100808354040283529160200191611a3a565b820191905f5260205f20905b815481529060010190602001808311611a1d57829003601f168201915b5050505050905090565b60605f6001611a5284611d45565b0190505f8167ffffffffffffffff811115611a7057611a6f612244565b5b6040519080825280601f01601f191660200182016040528015611aa25781602001600182028036833780820191505090505b5090505f82602001820190505b600115611b03578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611af857611af7612e8b565b5b0494505f8503611aaf575b819350505050919050565b5f7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c205460201c9050919050565b5f5b600115611b645760208320905080835281825f03068110611b48575b818106905092915050565b5f8060045f8581526020019081526020015f205490505f600184611b939190612827565b90505f60045f8381526020019081526020015f205490505f8314611bb75782611bb9565b855b9350818614611be7575f8114611bcf5780611bd1565b815b60045f8881526020019081526020015f20819055505b5f8114611c035760045f8381526020019081526020015f205f90555b50505092915050565b611c175f83836115cc565b8160601b60601c915081611c325763ea553b345f526004601cfd5b805f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f208101810180548060601b15611c795763c991cbb15f526004601cfd5b8381178255835f52601c600c20600181540163ffffffff8116611ca3576301336cea5f526004601cfd5b808255505082845f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a45050611cdc5f83836115d1565b5050565b5f611cea836113f8565b90505f8282611cf99190612eb8565b90505f611d0585611b0e565b9050611d37858277ffffffffffffffffffffffffffffffffffffffffffffffff1660c08563ffffffff16901b17611e96565b5050505050565b5f33905090565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611da1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611d9757611d96612e8b565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611dde576d04ee2d6d415b85acef81000000008381611dd457611dd3612e8b565b5b0492506020810190505b662386f26fc100008310611e0d57662386f26fc100008381611e0357611e02612e8b565b5b0492506010810190505b6305f5e1008310611e36576305f5e1008381611e2c57611e2b612e8b565b5b0492506008810190505b6127108310611e5b576127108381611e5157611e50612e8b565b5b0492506004810190505b60648310611e7e5760648381611e7457611e73612e8b565b5b0492506002810190505b600a8310611e8d576001810190505b80915050919050565b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c2080548060201c831860201b8118825550505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611f1c81611ee8565b8114611f26575f80fd5b50565b5f81359050611f3781611f13565b92915050565b5f60208284031215611f5257611f51611ee0565b5b5f611f5f84828501611f29565b91505092915050565b5f8115159050919050565b611f7c81611f68565b82525050565b5f602082019050611f955f830184611f73565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611fd2578082015181840152602081019050611fb7565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611ff782611f9b565b6120018185611fa5565b9350612011818560208601611fb5565b61201a81611fdd565b840191505092915050565b5f6020820190508181035f83015261203d8184611fed565b905092915050565b5f819050919050565b61205781612045565b8114612061575f80fd5b50565b5f813590506120728161204e565b92915050565b5f6020828403121561208d5761208c611ee0565b5b5f61209a84828501612064565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6120cc826120a3565b9050919050565b6120dc816120c2565b82525050565b5f6020820190506120f55f8301846120d3565b92915050565b612104816120c2565b811461210e575f80fd5b50565b5f8135905061211f816120fb565b92915050565b5f806040838503121561213b5761213a611ee0565b5b5f61214885828601612111565b925050602061215985828601612064565b9150509250929050565b61216c81612045565b82525050565b5f6020820190506121855f830184612163565b92915050565b5f805f606084860312156121a2576121a1611ee0565b5b5f6121af86828701612111565b93505060206121c086828701612111565b92505060406121d186828701612064565b9150509250925092565b5f60ff82169050919050565b6121f0816121db565b81146121fa575f80fd5b50565b5f8135905061220b816121e7565b92915050565b5f6020828403121561222657612225611ee0565b5b5f612233848285016121fd565b91505092915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61227a82611fdd565b810181811067ffffffffffffffff8211171561229957612298612244565b5b80604052505050565b5f6122ab611ed7565b90506122b78282612271565b919050565b5f67ffffffffffffffff8211156122d6576122d5612244565b5b6122df82611fdd565b9050602081019050919050565b828183375f83830152505050565b5f61230c612307846122bc565b6122a2565b90508281526020810184848401111561232857612327612240565b5b6123338482856122ec565b509392505050565b5f82601f83011261234f5761234e61223c565b5b813561235f8482602086016122fa565b91505092915050565b5f6020828403121561237d5761237c611ee0565b5b5f82013567ffffffffffffffff81111561239a57612399611ee4565b5b6123a68482850161233b565b91505092915050565b5f80fd5b5f80fd5b5f8083601f8401126123cc576123cb61223c565b5b8235905067ffffffffffffffff8111156123e9576123e86123af565b5b602083019150836020820283011115612405576124046123b3565b5b9250929050565b5f8083601f8401126124215761242061223c565b5b8235905067ffffffffffffffff81111561243e5761243d6123af565b5b60208301915083602082028301111561245a576124596123b3565b5b9250929050565b5f805f806040858703121561247957612478611ee0565b5b5f85013567ffffffffffffffff81111561249657612495611ee4565b5b6124a2878288016123b7565b9450945050602085013567ffffffffffffffff8111156124c5576124c4611ee4565b5b6124d18782880161240c565b925092505092959194509250565b5f602082840312156124f4576124f3611ee0565b5b5f61250184828501612111565b91505092915050565b5f612514826120a3565b9050919050565b6125248161250a565b82525050565b5f60208201905061253d5f83018461251b565b92915050565b61254c81611f68565b8114612556575f80fd5b50565b5f8135905061256781612543565b92915050565b5f806040838503121561258357612582611ee0565b5b5f61259085828601612111565b92505060206125a185828601612559565b9150509250929050565b6125b4816121db565b82525050565b5f6040820190506125cd5f8301856125ab565b6125da60208301846125ab565b9392505050565b5f6020820190506125f45f8301846125ab565b92915050565b5f8083601f84011261260f5761260e61223c565b5b8235905067ffffffffffffffff81111561262c5761262b6123af565b5b602083019150836001820283011115612648576126476123b3565b5b9250929050565b5f805f805f6080868803121561266857612667611ee0565b5b5f61267588828901612111565b955050602061268688828901612111565b945050604061269788828901612064565b935050606086013567ffffffffffffffff8111156126b8576126b7611ee4565b5b6126c4888289016125fa565b92509250509295509295909350565b5f63ffffffff82169050919050565b6126eb816126d3565b82525050565b5f6020820190506127045f8301846126e2565b92915050565b5f80604083850312156127205761271f611ee0565b5b5f61272d85828601612111565b925050602061273e85828601612111565b9150509250929050565b6127518161250a565b811461275b575f80fd5b50565b5f8135905061276c81612748565b92915050565b5f6020828403121561278757612786611ee0565b5b5f6127948482850161275e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806127e157607f821691505b6020821081036127f4576127f361279d565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61283182612045565b915061283c83612045565b9250828203905081811115612854576128536127fa565b5b92915050565b7f4e6f7420656c696769626c6500000000000000000000000000000000000000005f82015250565b5f61288e600c83611fa5565b91506128998261285a565b602082019050919050565b5f6020820190508181035f8301526128bb81612882565b9050919050565b7f4e6f7420656e6f75676820636c61696d61626c6520746f6b656e7300000000005f82015250565b5f6128f6601b83611fa5565b9150612901826128c2565b602082019050919050565b5f6020820190508181035f830152612923816128ea565b9050919050565b5f61293482612045565b915061293f83612045565b9250828201905080821115612957576129566127fa565b5b92915050565b7f537570706c79206c696d697420657863656564000000000000000000000000005f82015250565b5f612991601383611fa5565b915061299c8261295d565b602082019050919050565b5f6020820190508181035f8301526129be81612985565b9050919050565b5f6129cf826121db565b91506129da836121db565b9250828201905060ff8111156129f3576129f26127fa565b5b92915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302612a557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612a1a565b612a5f8683612a1a565b95508019841693508086168417925050509392505050565b5f819050919050565b5f612a9a612a95612a9084612045565b612a77565b612045565b9050919050565b5f819050919050565b612ab383612a80565b612ac7612abf82612aa1565b848454612a26565b825550505050565b5f90565b612adb612acf565b612ae6818484612aaa565b505050565b5b81811015612b0957612afe5f82612ad3565b600181019050612aec565b5050565b601f821115612b4e57612b1f816129f9565b612b2884612a0b565b81016020851015612b37578190505b612b4b612b4385612a0b565b830182612aeb565b50505b505050565b5f82821c905092915050565b5f612b6e5f1984600802612b53565b1980831691505092915050565b5f612b868383612b5f565b9150826002028217905092915050565b612b9f82611f9b565b67ffffffffffffffff811115612bb857612bb7612244565b5b612bc282546127ca565b612bcd828285612b0d565b5f60209050601f831160018114612bfe575f8415612bec578287015190505b612bf68582612b7b565b865550612c5d565b601f198416612c0c866129f9565b5f5b82811015612c3357848901518255600182019150602085019450602081019050612c0e565b86831015612c505784890151612c4c601f891682612b5f565b8355505b6001600288020188555050505b505050505050565b7f4e62206164647265737320616e64206e62207175616e746974696573206d75735f8201527f7420626520657175616c00000000000000000000000000000000000000000000602082015250565b5f612cbf602a83611fa5565b9150612cca82612c65565b604082019050919050565b5f6020820190508181035f830152612cec81612cb3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612d2a826121db565b9150612d35836121db565b9250828203905060ff811115612d4e57612d4d6127fa565b5b92915050565b7f756e6b6e6f7720746f6b656e00000000000000000000000000000000000000005f82015250565b5f612d88600c83611fa5565b9150612d9382612d54565b602082019050919050565b5f6020820190508181035f830152612db581612d7c565b9050919050565b5f81905092915050565b5f612dd082611f9b565b612dda8185612dbc565b9350612dea818560208601611fb5565b80840191505092915050565b5f612e018285612dc6565b9150612e0d8284612dc6565b91508190509392505050565b5f819050919050565b612e33612e2e82612045565b612e19565b82525050565b5f612e448285612e22565b602082019150612e548284612e22565b6020820191508190509392505050565b5f612e6e82612045565b91505f8203612e8057612e7f6127fa565b5b600182039050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612ec2826126d3565b9150612ecd836126d3565b9250828201905063ffffffff811115612ee957612ee86127fa565b5b9291505056fea2646970667358221220b759f54012460361b42f3a4227bec927bf17ab62cd396622764adcd08386126364736f6c63430008170033
Deployed Bytecode Sourcemap
123294:2642:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42035:383;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119876:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35086:553;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35942:121;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119754:114;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37770:3015;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123423:71;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125519:414;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124028:99;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124762:345;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;40859:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125113:400;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;33914:341;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123395:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34405:541;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;23418:103;;;;;;;;;;;;;:::i;:::-;;123806:102;;;:::i;:::-;;22743:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123499:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119984:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36690:713;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123607:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;124614:142;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41577:244;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124232:271;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124509:99;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119495:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119456:30;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120096:138;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36157:389;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;23676:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123914:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;42035:383;42111:11;42221;42216:3;42212:21;42388:10;42385:1;42382:17;42368:10;42365:1;42362:17;42349:10;42346:1;42343:17;42340:40;42337:63;42327:73;;42188:223;42035:383;;;:::o;119876:100::-;119930:13;119963:5;119956:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119876:100;:::o;35086:553::-;35148:14;35256:2;35250:4;35243:16;35286:24;35280:4;35273:38;35378:4;35372;35362:21;35358:2;35354:30;35350:2;35346:39;35431:13;35425:20;35421:2;35417:29;35413:2;35409:38;35399:170;;35481:10;35475:4;35468:24;35549:4;35543;35536:18;35399:170;35606:13;35603:1;35599:21;35593:28;35583:38;;35228:404;35086:553;;;:::o;35942:121::-;36022:33;36031:10;36043:7;36052:2;36022:8;:33::i;:::-;35942:121;;:::o;119754:114::-;119806:7;119845:15;;119833:9;:27;;;;:::i;:::-;119826:34;;119754:114;:::o;37770:3015::-;37864:34;37885:4;37891:2;37895;37864:20;:34::i;:::-;38048:1;38044:6;38040:2;38036:15;38093:4;38077:14;38073:25;38065:33;;38138:2;38122:14;38118:23;38112:29;;38205:2;38199:4;38192:16;38264:8;38238:24;38235:38;38229:4;38222:52;38341:4;38335;38325:21;38321:2;38317:30;38313:2;38309:39;38391:13;38385:20;38452:15;38436:14;38432:36;38579:4;38572:5;38569:15;38562:5;38558:27;38548:335;;38616:5;38606:149;;38659:10;38653:4;38646:24;38731:4;38725;38718:18;38606:149;38786:10;38780:4;38773:24;38863:4;38857;38850:18;38548:335;38955:2;38945:138;;38991:10;38985:4;38978:24;39063:4;39057;39050:18;38945:138;39185:4;39179;39172:18;39244:13;39241:1;39237:21;39231:28;39392:15;39382:8;39379:29;39372:4;39362:8;39359:18;39356:53;39346:293;;39466:4;39460;39450:21;39444:28;39434:186;;39514:10;39508:4;39501:24;39592:4;39586;39579:18;39434:186;39346:293;39712:15;39709:55;;;39760:1;39744:13;39741:1;39737:21;39730:32;39709:55;39153:626;39885:2;39879:4;39875:13;39858:15;39854:35;39839:13;39832:58;40007:4;40001;39991:21;40082:1;40064:15;40058:22;40054:30;40037:15;40030:55;39949:151;40189:2;40183:4;40176:16;40247:4;40241;40231:21;40323:1;40307:13;40301:20;40297:28;40378:20;40357:19;40353:46;40343:195;;40437:10;40431:4;40424:24;40514:4;40508;40501:18;40343:195;40578:19;40563:13;40556:42;40157:456;;40720:2;40716;40710:4;40683:25;40677:4;40671;40666:57;37962:2772;;;;40744:33;40764:4;40770:2;40774;40744:19;:33::i;:::-;37770:3015;;;:::o;123423:71::-;;;;;;;;;;;;;:::o;125519:414::-;125606:1;125582:21;125592:10;125582:9;:21::i;:::-;:25;;;125574:50;;;;;;;;;;;;:::i;:::-;;;;;;;;;125664:11;125639:36;;:21;125649:10;125639:9;:21::i;:::-;:36;;;;125631:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;125751:11;125735:27;;:13;:11;:13::i;:::-;:27;;;;:::i;:::-;125722:9;:40;;125714:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;125826:11;125793:9;:21;125803:10;125793:21;;;;;;;;;;;;;;;:29;;;:44;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;125844:36;125856:10;125868:11;125844:36;;:11;:36::i;:::-;125899:10;125892:35;;;125911:15;125892:35;;;;;;:::i;:::-;;;;;;;;125519:414;:::o;124028:99::-;22629:13;:11;:13::i;:::-;124110:11:::1;124100:7;:21;;;;;;:::i;:::-;;124028:99:::0;:::o;124762:345::-;22629:13;:11;:13::i;:::-;124910:11:::1;;:18;;124884:15;;:22;;:44;124876:99;;;;;;;;;;;;:::i;:::-;;;;;;;;;124987:6;124982:120;125003:15;;:22;;124999:1;:26;124982:120;;;125080:11;;125092:1;125080:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125041:9;:29;125051:15;;125067:1;125051:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125041:29;;;;;;;;;;;;;;;:35;;;:53;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;125027:3;;;;;;;124982:120;;;;124762:345:::0;;;;:::o;40859:201::-;40957:26;40970:4;40976:2;40980;40957:12;:26::i;:::-;40998:12;41007:2;40998:8;:12::i;:::-;40994:58;;;41012:40;41035:4;41041:2;41045;41012:40;;;;;;;;;;;;:22;:40::i;:::-;40994:58;40859:201;;;:::o;125113:400::-;22629:13;:11;:13::i;:::-;125254:11:::1;;:18;;125233:10;;:17;;:39;125225:94;;;;;;;;;;;;:::i;:::-;;;;;;;;;125331:6;125326:182;125347:10;;:17;;125343:1;:21;125326:182;;;125429:1;125411:11;;125423:1;125411:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125384:24;125394:10;;125405:1;125394:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125384:9;:24::i;:::-;:41;;;;:::i;:::-;:46;;;125380:121;;125477:11;;125489:1;125477:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125443:9;:24;125453:10;;125464:1;125453:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125443:24;;;;;;;;;;;;;;;:30;;;:48;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;125380:121;125366:3;;;;;;;125326:182;;;;125113:400:::0;;;;:::o;33914:341::-;33972:14;34008:12;34017:2;34008:8;:12::i;:::-;33999:21;;34109:6;34099:138;;34149:10;34143:4;34136:24;34217:4;34211;34204:18;34099:138;33914:341;;;:::o;123395:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;34405:541::-;34468:14;34628:5;34618:146;;34667:10;34661:4;34654:24;34744:4;34738;34731:18;34618:146;34791:24;34785:4;34778:38;34843:5;34837:4;34830:19;34907:20;34899:4;34893;34883:21;34877:28;34873:55;34863:65;;34405:541;;;:::o;23418:103::-;22629:13;:11;:13::i;:::-;23483:30:::1;23510:1;23483:18;:30::i;:::-;23418:103::o:0;123806:102::-;22629:13;:11;:13::i;:::-;123861:9:::1;;;;;;;;;;;:18;;:41;123880:21;123861:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;123806:102::o:0;22743:87::-;22789:7;22816:6;;;;;;;;;;;22809:13;;22743:87;:::o;123499:32::-;;;;;;;;;;;;;:::o;119984:104::-;120040:13;120073:7;120066:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119984:104;:::o;36690:713::-;36905:10;36898:18;36891:26;36877:40;;37012:8;37006:4;36999:22;37048:31;37042:4;37035:45;37107:8;37101:4;37094:22;37160:10;37153:4;37147;37137:21;37130:41;37243:10;37237:4;37230:24;37360:8;37356:2;37352:17;37348:2;37344:26;37334:8;37299:33;37293:4;37287;37268:117;36690:713;;:::o;123607:48::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;124614:142::-;124678:5;124725:9;:17;124735:6;124725:17;;;;;;;;;;;;;;;:25;;;;;;;;;;;;124699:9;:17;124709:6;124699:17;;;;;;;;;;;;;;;:23;;;;;;;;;;;;:51;;;;:::i;:::-;124692:58;;124614:142;;;:::o;41577:244::-;41716:26;41729:4;41735:2;41739;41716:12;:26::i;:::-;41757:12;41766:2;41757:8;:12::i;:::-;41753:60;;;41771:42;41794:4;41800:2;41804;41808:4;;41771:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:22;:42::i;:::-;41753:60;41577:244;;;;;:::o;124232:271::-;124305:13;124335:16;124343:7;124335;:16::i;:::-;124327:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;124375:17;124395:10;:8;:10::i;:::-;124375:30;;124439:1;124425:3;124419:17;:21;:78;;;;;;;;;;;;;;;;;124467:3;124472:18;:7;:16;:18::i;:::-;124450:41;;;;;;;;;:::i;:::-;;;;;;;;;;;;;124419:78;124412:85;;;124232:271;;;:::o;124509:99::-;124566:4;124586:16;124594:7;124586;:16::i;:::-;124579:23;;124509:99;;;:::o;119495:34::-;;;:::o;119456:30::-;;;;:::o;120096:138::-;120163:6;120222:3;120196:22;120211:6;120196:14;:22::i;:::-;:29;;;;120182:44;;120096:138;;;:::o;36157:389::-;36265:11;36375:8;36369:4;36362:22;36411:31;36405:4;36398:45;36470:5;36464:4;36457:19;36522:4;36516;36506:21;36500:28;36490:38;;36157:389;;;;:::o;23676:220::-;22629:13;:11;:13::i;:::-;23781:1:::1;23761:22;;:8;:22;;::::0;23757:93:::1;;23835:1;23807:31;;;;;;;;;;;:::i;:::-;;;;;;;;23757:93;23860:28;23879:8;23860:18;:28::i;:::-;23676:220:::0;:::o;123914:108::-;22629:13;:11;:13::i;:::-;124003::::1;123991:9;;:25;;;;;;;;;;;;;;;;;;123914:108:::0;:::o;54585:1438::-;54767:1;54763:6;54759:2;54755:15;54815:7;54799:14;54795:28;54784:39;;54863:2;54847:14;54843:23;54837:29;;54934:2;54928:4;54921:16;54993:2;54967:24;54964:32;54958:4;54951:46;55064:4;55058;55048:21;55044:2;55040:30;55036:2;55032:39;55124:13;55118:20;55102:14;55098:41;55211:5;55201:137;;55250:10;55244:4;55237:24;55318:4;55312;55305:18;55201:137;55516:5;55512:2;55509:13;55504:2;55497:10;55494:29;55484:286;;55557:5;55551:4;55544:19;55613:4;55607;55597:21;55591:28;55581:174;;55657:10;55651:4;55644:24;55731:4;55725;55718:18;55581:174;55484:286;55881:7;55865:13;55862:1;55858:21;55851:38;56002:2;55993:7;55986:5;55959:25;55953:4;55947;55942:63;54681:1335;;;54585:1438;;;:::o;63335:87::-;;;;:::o;63522:86::-;;;;:::o;120242:939::-;120341:9;120327:23;;:10;:23;;;120323:57;;120359:21;;;;;;;;;;;;;;120323:57;120409:1;120395:10;:15;120391:53;;120419:25;;;;;;;;;;;;;;120391:53;120477:10;120459:15;;:28;120455:67;;;120496:26;;;;;;;;;;;;;;120455:67;120535:24;120562:109;;;;;;;;120624:15;120641:16;120593:75;;;;;;;;;:::i;:::-;;;;;;;;;;;;;120583:86;;;;;;120575:95;;120562:109;;;120535:136;;120684:30;120717:15;;120684:48;;120750:9;120745:319;120765:10;120761:1;:14;120745:319;;;120794:19;120816:36;120829:22;120816:4;:12;;:36;;;;:::i;:::-;120794:58;;120869:15;120887:61;120912:11;120925:22;120887:24;:61::i;:::-;120869:79;;120965:18;120971:2;120975:7;120965:5;:18::i;:::-;121000:24;;;;:::i;:::-;;;121048:3;;;;;120779:285;;120745:319;;;;121076:46;121099:2;121110:10;121076:22;:46::i;:::-;121151:22;121133:15;:40;;;;120312:869;;120242:939;;:::o;22908:166::-;22979:12;:10;:12::i;:::-;22968:23;;:7;:5;:7::i;:::-;:23;;;22964:103;;23042:12;:10;:12::i;:::-;23015:40;;;;;;;;;;;:::i;:::-;;;;;;;;22964:103;22908:166::o;63965:217::-;64016:11;64130:1;64118:14;64108:24;;63965:217;;;:::o;64345:1416::-;64580:4;64574:11;64631:10;64665:24;64662:1;64655:35;64725:8;64718:4;64715:1;64711:12;64704:30;64834:4;64830:2;64826:13;64822:2;64818:22;64811:4;64808:1;64804:12;64797:44;64876:2;64869:4;64866:1;64862:12;64855:24;64914:4;64907;64904:1;64900:12;64893:26;64948:4;64942:11;64988:1;64981:4;64978:1;64974:12;64967:23;65007:1;65004:71;;;65070:1;65063:4;65060:1;65056:12;65053:1;65046:4;65040;65036:15;65033:1;65026:5;65015:57;65011:62;65004:71;65189:4;65186:1;65179:4;65176:1;65172:12;65165:4;65162:1;65158:12;65155:1;65151:2;65144:5;65139:55;65129:351;;65218:16;65215:220;;;65347:16;65341:4;65335;65320:44;65399:16;65393:4;65386:30;65215:220;65463:1;65460;65453:12;65129:351;65574:24;65569:3;65565:34;65561:1;65555:8;65552:48;65542:201;;65634:10;65628:4;65621:24;65723:4;65717;65710:18;65542:201;64516:1238;;;64345:1416;;;;:::o;43213:330::-;43274:14;43382:2;43376:4;43369:16;43412:24;43406:4;43399:38;43515:4;43509;43499:21;43495:2;43491:30;43487:2;43483:39;43477:46;43473:2;43469:55;43465:2;43461:64;43451:74;;43213:330;;;:::o;24056:191::-;24130:16;24149:6;;;;;;;;;;;24130:25;;24175:8;24166:6;;:17;;;;;;;;;;;;;;;;;;24230:8;24199:40;;24220:8;24199:40;;;;;;;;;;;;24119:128;24056:191;:::o;42757:317::-;42817:11;42922:2;42916:4;42909:16;42952:24;42946:4;42939:38;43047:4;43041;43031:21;43027:2;43023:30;43019:2;43015:39;43009:46;43005:2;43001:55;42991:65;;42757:317;;;:::o;124133:93::-;124184:13;124213:7;124206:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124133:93;:::o;17524:718::-;17580:13;17631:14;17668:1;17648:17;17659:5;17648:10;:17::i;:::-;:21;17631:38;;17684:20;17718:6;17707:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17684:41;;17740:11;17869:6;17865:2;17861:15;17853:6;17849:28;17842:35;;17906:290;17913:4;17906:290;;;17938:5;;;;;;;;18080:10;18075:2;18068:5;18064:14;18059:32;18054:3;18046:46;18138:2;18129:11;;;;;;:::i;:::-;;;;;18172:1;18163:5;:10;17906:290;18159:21;17906:290;18217:6;18210:13;;;;;17524:718;;;:::o;44079:308::-;44142:14;44250:24;44244:4;44237:38;44302:5;44296:4;44289:19;44362:4;44356;44346:21;44340:28;44336:2;44332:37;44322:47;;44079:308;;;:::o;68216:419::-;68289:14;68384:191;68391:1;68384:191;;;68441:4;68435;68425:21;68415:31;;68477:6;68471:4;68464:20;68542:5;68534;68531:1;68527:13;68523:25;68515:6;68512:37;68384:191;68502:58;68384:191;68611:5;68603:6;68599:18;68589:28;;68216:419;;;;:::o;121751:636::-;121867:14;121899:18;121920:16;:28;121937:10;121920:28;;;;;;;;;;;;121899:49;;121959:17;122007:1;121979:25;:29;;;;:::i;:::-;121959:49;;122019:22;122044:16;:27;122061:9;122044:27;;;;;;;;;;;;122019:52;;122107:1;122093:10;:15;:41;;122124:10;122093:41;;;122111:10;122093:41;122084:50;;122165:9;122151:10;:23;122147:135;;122240:1;122222:14;:19;:48;;122256:14;122222:48;;;122244:9;122222:48;122191:16;:28;122208:10;122191:28;;;;;;;;;;;:79;;;;122147:135;122316:1;122298:14;:19;122294:86;;122341:16;:27;122358:9;122341:27;;;;;;;;;;;122334:34;;;122294:86;121888:499;;;121751:636;;;;:::o;46738:1686::-;46805:40;46834:1;46838:2;46842;46805:20;:40::i;:::-;46983:2;46979;46975:11;46971:2;46967:20;46961:26;;47059:2;47049:138;;47095:10;47089:4;47082:24;47167:4;47161;47154:18;47049:138;47251:2;47245:4;47238:16;47281:24;47275:4;47268:38;47373:4;47367;47357:21;47353:2;47349:30;47345:2;47341:39;47423:13;47417:20;47510:15;47506:2;47502:24;47499:149;;;47559:10;47553:4;47546:24;47628:4;47622;47615:18;47499:149;47739:2;47722:15;47719:23;47704:13;47697:46;47837:2;47831:4;47824:16;47893:4;47887;47877:21;47965:1;47951:11;47945:18;47941:26;48018:20;47999:17;47995:44;47985:193;;48077:10;48071:4;48064:24;48154:4;48148;48141:18;47985:193;48216:17;48203:11;48196:38;47805:444;;48353:2;48349;48346:1;48319:25;48313:4;48307;48302:54;46909:1458;;48377:39;48405:1;48409:2;48413;48377:19;:39::i;:::-;46738:1686;;:::o;122818:390::-;122902:16;122921:20;122934:6;122921:12;:20::i;:::-;122902:39;;122952:23;122997:8;122978:9;:28;;;;:::i;:::-;122952:54;;123017:15;123035:22;123050:6;123035:14;:22::i;:::-;123017:40;;123070:130;123099:6;123180:7;123164:25;;123157:3;123136:16;123128:25;;:32;;123120:69;123070:14;:130::i;:::-;122891:317;;;122818:390;;:::o;20754:98::-;20807:7;20834:10;20827:17;;20754:98;:::o;12590:948::-;12643:7;12663:14;12680:1;12663:18;;12730:8;12721:5;:17;12717:106;;12768:8;12759:17;;;;;;:::i;:::-;;;;;12805:2;12795:12;;;;12717:106;12850:8;12841:5;:17;12837:106;;12888:8;12879:17;;;;;;:::i;:::-;;;;;12925:2;12915:12;;;;12837:106;12970:8;12961:5;:17;12957:106;;13008:8;12999:17;;;;;;:::i;:::-;;;;;13045:2;13035:12;;;;12957:106;13090:7;13081:5;:16;13077:103;;13127:7;13118:16;;;;;;:::i;:::-;;;;;13163:1;13153:11;;;;13077:103;13207:7;13198:5;:16;13194:103;;13244:7;13235:16;;;;;;:::i;:::-;;;;;13280:1;13270:11;;;;13194:103;13324:7;13315:5;:16;13311:103;;13361:7;13352:16;;;;;;:::i;:::-;;;;;13397:1;13387:11;;;;13311:103;13441:7;13432:5;:16;13428:68;;13479:1;13469:11;;;;13428:68;13524:6;13517:13;;;12590:948;;;:::o;44643:416::-;44799:24;44793:4;44786:38;44851:5;44845:4;44838:19;44906:4;44900;44890:21;44945:11;44939:18;45030:6;45026:2;45022:15;45015:5;45011:27;45007:2;45003:36;44995:6;44991:49;44978:11;44971:70;44771:281;;44643:416;;:::o;7:75:1:-;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:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:619::-;5319:6;5327;5335;5384:2;5372:9;5363:7;5359:23;5355:32;5352:119;;;5390:79;;:::i;:::-;5352:119;5510:1;5535:53;5580:7;5571:6;5560:9;5556:22;5535:53;:::i;:::-;5525:63;;5481:117;5637:2;5663:53;5708:7;5699:6;5688:9;5684:22;5663:53;:::i;:::-;5653:63;;5608:118;5765:2;5791:53;5836:7;5827:6;5816:9;5812:22;5791:53;:::i;:::-;5781:63;;5736:118;5242:619;;;;;:::o;5867:86::-;5902:7;5942:4;5935:5;5931:16;5920:27;;5867:86;;;:::o;5959:118::-;6030:22;6046:5;6030:22;:::i;:::-;6023:5;6020:33;6010:61;;6067:1;6064;6057:12;6010:61;5959:118;:::o;6083:135::-;6127:5;6165:6;6152:20;6143:29;;6181:31;6206:5;6181:31;:::i;:::-;6083:135;;;;:::o;6224:325::-;6281:6;6330:2;6318:9;6309:7;6305:23;6301:32;6298:119;;;6336:79;;:::i;:::-;6298:119;6456:1;6481:51;6524:7;6515:6;6504:9;6500:22;6481:51;:::i;:::-;6471:61;;6427:115;6224:325;;;;:::o;6555:117::-;6664:1;6661;6654:12;6678:117;6787:1;6784;6777:12;6801:180;6849:77;6846:1;6839:88;6946:4;6943:1;6936:15;6970:4;6967:1;6960:15;6987:281;7070:27;7092:4;7070:27;:::i;:::-;7062:6;7058:40;7200:6;7188:10;7185:22;7164:18;7152:10;7149:34;7146:62;7143:88;;;7211:18;;:::i;:::-;7143:88;7251:10;7247:2;7240:22;7030:238;6987:281;;:::o;7274:129::-;7308:6;7335:20;;:::i;:::-;7325:30;;7364:33;7392:4;7384:6;7364:33;:::i;:::-;7274:129;;;:::o;7409:308::-;7471:4;7561:18;7553:6;7550:30;7547:56;;;7583:18;;:::i;:::-;7547:56;7621:29;7643:6;7621:29;:::i;:::-;7613:37;;7705:4;7699;7695:15;7687:23;;7409:308;;;:::o;7723:146::-;7820:6;7815:3;7810;7797:30;7861:1;7852:6;7847:3;7843:16;7836:27;7723:146;;;:::o;7875:425::-;7953:5;7978:66;7994:49;8036:6;7994:49;:::i;:::-;7978:66;:::i;:::-;7969:75;;8067:6;8060:5;8053:21;8105:4;8098:5;8094:16;8143:3;8134:6;8129:3;8125:16;8122:25;8119:112;;;8150:79;;:::i;:::-;8119:112;8240:54;8287:6;8282:3;8277;8240:54;:::i;:::-;7959:341;7875:425;;;;;:::o;8320:340::-;8376:5;8425:3;8418:4;8410:6;8406:17;8402:27;8392:122;;8433:79;;:::i;:::-;8392:122;8550:6;8537:20;8575:79;8650:3;8642:6;8635:4;8627:6;8623:17;8575:79;:::i;:::-;8566:88;;8382:278;8320:340;;;;:::o;8666:509::-;8735:6;8784:2;8772:9;8763:7;8759:23;8755:32;8752:119;;;8790:79;;:::i;:::-;8752:119;8938:1;8927:9;8923:17;8910:31;8968:18;8960:6;8957:30;8954:117;;;8990:79;;:::i;:::-;8954:117;9095:63;9150:7;9141:6;9130:9;9126:22;9095:63;:::i;:::-;9085:73;;8881:287;8666:509;;;;:::o;9181:117::-;9290:1;9287;9280:12;9304:117;9413:1;9410;9403:12;9444:568;9517:8;9527:6;9577:3;9570:4;9562:6;9558:17;9554:27;9544:122;;9585:79;;:::i;:::-;9544:122;9698:6;9685:20;9675:30;;9728:18;9720:6;9717:30;9714:117;;;9750:79;;:::i;:::-;9714:117;9864:4;9856:6;9852:17;9840:29;;9918:3;9910:4;9902:6;9898:17;9888:8;9884:32;9881:41;9878:128;;;9925:79;;:::i;:::-;9878:128;9444:568;;;;;:::o;10033:566::-;10104:8;10114:6;10164:3;10157:4;10149:6;10145:17;10141:27;10131:122;;10172:79;;:::i;:::-;10131:122;10285:6;10272:20;10262:30;;10315:18;10307:6;10304:30;10301:117;;;10337:79;;:::i;:::-;10301:117;10451:4;10443:6;10439:17;10427:29;;10505:3;10497:4;10489:6;10485:17;10475:8;10471:32;10468:41;10465:128;;;10512:79;;:::i;:::-;10465:128;10033:566;;;;;:::o;10605:930::-;10725:6;10733;10741;10749;10798:2;10786:9;10777:7;10773:23;10769:32;10766:119;;;10804:79;;:::i;:::-;10766:119;10952:1;10941:9;10937:17;10924:31;10982:18;10974:6;10971:30;10968:117;;;11004:79;;:::i;:::-;10968:117;11117:80;11189:7;11180:6;11169:9;11165:22;11117:80;:::i;:::-;11099:98;;;;10895:312;11274:2;11263:9;11259:18;11246:32;11305:18;11297:6;11294:30;11291:117;;;11327:79;;:::i;:::-;11291:117;11440:78;11510:7;11501:6;11490:9;11486:22;11440:78;:::i;:::-;11422:96;;;;11217:311;10605:930;;;;;;;:::o;11541:329::-;11600:6;11649:2;11637:9;11628:7;11624:23;11620:32;11617:119;;;11655:79;;:::i;:::-;11617:119;11775:1;11800:53;11845:7;11836:6;11825:9;11821:22;11800:53;:::i;:::-;11790:63;;11746:117;11541:329;;;;:::o;11876:104::-;11921:7;11950:24;11968:5;11950:24;:::i;:::-;11939:35;;11876:104;;;:::o;11986:142::-;12089:32;12115:5;12089:32;:::i;:::-;12084:3;12077:45;11986:142;;:::o;12134:254::-;12243:4;12281:2;12270:9;12266:18;12258:26;;12294:87;12378:1;12367:9;12363:17;12354:6;12294:87;:::i;:::-;12134:254;;;;:::o;12394:116::-;12464:21;12479:5;12464:21;:::i;:::-;12457:5;12454:32;12444:60;;12500:1;12497;12490:12;12444:60;12394:116;:::o;12516:133::-;12559:5;12597:6;12584:20;12575:29;;12613:30;12637:5;12613:30;:::i;:::-;12516:133;;;;:::o;12655:468::-;12720:6;12728;12777:2;12765:9;12756:7;12752:23;12748:32;12745:119;;;12783:79;;:::i;:::-;12745:119;12903:1;12928:53;12973:7;12964:6;12953:9;12949:22;12928:53;:::i;:::-;12918:63;;12874:117;13030:2;13056:50;13098:7;13089:6;13078:9;13074:22;13056:50;:::i;:::-;13046:60;;13001:115;12655:468;;;;;:::o;13129:112::-;13212:22;13228:5;13212:22;:::i;:::-;13207:3;13200:35;13129:112;;:::o;13247:316::-;13360:4;13398:2;13387:9;13383:18;13375:26;;13411:67;13475:1;13464:9;13460:17;13451:6;13411:67;:::i;:::-;13488:68;13552:2;13541:9;13537:18;13528:6;13488:68;:::i;:::-;13247:316;;;;;:::o;13569:214::-;13658:4;13696:2;13685:9;13681:18;13673:26;;13709:67;13773:1;13762:9;13758:17;13749:6;13709:67;:::i;:::-;13569:214;;;;:::o;13802:552::-;13859:8;13869:6;13919:3;13912:4;13904:6;13900:17;13896:27;13886:122;;13927:79;;:::i;:::-;13886:122;14040:6;14027:20;14017:30;;14070:18;14062:6;14059:30;14056:117;;;14092:79;;:::i;:::-;14056:117;14206:4;14198:6;14194:17;14182:29;;14260:3;14252:4;14244:6;14240:17;14230:8;14226:32;14223:41;14220:128;;;14267:79;;:::i;:::-;14220:128;13802:552;;;;;:::o;14360:963::-;14457:6;14465;14473;14481;14489;14538:3;14526:9;14517:7;14513:23;14509:33;14506:120;;;14545:79;;:::i;:::-;14506:120;14665:1;14690:53;14735:7;14726:6;14715:9;14711:22;14690:53;:::i;:::-;14680:63;;14636:117;14792:2;14818:53;14863:7;14854:6;14843:9;14839:22;14818:53;:::i;:::-;14808:63;;14763:118;14920:2;14946:53;14991:7;14982:6;14971:9;14967:22;14946:53;:::i;:::-;14936:63;;14891:118;15076:2;15065:9;15061:18;15048:32;15107:18;15099:6;15096:30;15093:117;;;15129:79;;:::i;:::-;15093:117;15242:64;15298:7;15289:6;15278:9;15274:22;15242:64;:::i;:::-;15224:82;;;;15019:297;14360:963;;;;;;;;:::o;15329:93::-;15365:7;15405:10;15398:5;15394:22;15383:33;;15329:93;;;:::o;15428:115::-;15513:23;15530:5;15513:23;:::i;:::-;15508:3;15501:36;15428:115;;:::o;15549:218::-;15640:4;15678:2;15667:9;15663:18;15655:26;;15691:69;15757:1;15746:9;15742:17;15733:6;15691:69;:::i;:::-;15549:218;;;;:::o;15773:474::-;15841:6;15849;15898:2;15886:9;15877:7;15873:23;15869:32;15866:119;;;15904:79;;:::i;:::-;15866:119;16024:1;16049:53;16094:7;16085:6;16074:9;16070:22;16049:53;:::i;:::-;16039:63;;15995:117;16151:2;16177:53;16222:7;16213:6;16202:9;16198:22;16177:53;:::i;:::-;16167:63;;16122:118;15773:474;;;;;:::o;16253:138::-;16334:32;16360:5;16334:32;:::i;:::-;16327:5;16324:43;16314:71;;16381:1;16378;16371:12;16314:71;16253:138;:::o;16397:155::-;16451:5;16489:6;16476:20;16467:29;;16505:41;16540:5;16505:41;:::i;:::-;16397:155;;;;:::o;16558:345::-;16625:6;16674:2;16662:9;16653:7;16649:23;16645:32;16642:119;;;16680:79;;:::i;:::-;16642:119;16800:1;16825:61;16878:7;16869:6;16858:9;16854:22;16825:61;:::i;:::-;16815:71;;16771:125;16558:345;;;;:::o;16909:180::-;16957:77;16954:1;16947:88;17054:4;17051:1;17044:15;17078:4;17075:1;17068:15;17095:320;17139:6;17176:1;17170:4;17166:12;17156:22;;17223:1;17217:4;17213:12;17244:18;17234:81;;17300:4;17292:6;17288:17;17278:27;;17234:81;17362:2;17354:6;17351:14;17331:18;17328:38;17325:84;;17381:18;;:::i;:::-;17325:84;17146:269;17095:320;;;:::o;17421:180::-;17469:77;17466:1;17459:88;17566:4;17563:1;17556:15;17590:4;17587:1;17580:15;17607:194;17647:4;17667:20;17685:1;17667:20;:::i;:::-;17662:25;;17701:20;17719:1;17701:20;:::i;:::-;17696:25;;17745:1;17742;17738:9;17730:17;;17769:1;17763:4;17760:11;17757:37;;;17774:18;;:::i;:::-;17757:37;17607:194;;;;:::o;17807:162::-;17947:14;17943:1;17935:6;17931:14;17924:38;17807:162;:::o;17975:366::-;18117:3;18138:67;18202:2;18197:3;18138:67;:::i;:::-;18131:74;;18214:93;18303:3;18214:93;:::i;:::-;18332:2;18327:3;18323:12;18316:19;;17975:366;;;:::o;18347:419::-;18513:4;18551:2;18540:9;18536:18;18528:26;;18600:9;18594:4;18590:20;18586:1;18575:9;18571:17;18564:47;18628:131;18754:4;18628:131;:::i;:::-;18620:139;;18347:419;;;:::o;18772:177::-;18912:29;18908:1;18900:6;18896:14;18889:53;18772:177;:::o;18955:366::-;19097:3;19118:67;19182:2;19177:3;19118:67;:::i;:::-;19111:74;;19194:93;19283:3;19194:93;:::i;:::-;19312:2;19307:3;19303:12;19296:19;;18955:366;;;:::o;19327:419::-;19493:4;19531:2;19520:9;19516:18;19508:26;;19580:9;19574:4;19570:20;19566:1;19555:9;19551:17;19544:47;19608:131;19734:4;19608:131;:::i;:::-;19600:139;;19327:419;;;:::o;19752:191::-;19792:3;19811:20;19829:1;19811:20;:::i;:::-;19806:25;;19845:20;19863:1;19845:20;:::i;:::-;19840:25;;19888:1;19885;19881:9;19874:16;;19909:3;19906:1;19903:10;19900:36;;;19916:18;;:::i;:::-;19900:36;19752:191;;;;:::o;19949:169::-;20089:21;20085:1;20077:6;20073:14;20066:45;19949:169;:::o;20124:366::-;20266:3;20287:67;20351:2;20346:3;20287:67;:::i;:::-;20280:74;;20363:93;20452:3;20363:93;:::i;:::-;20481:2;20476:3;20472:12;20465:19;;20124:366;;;:::o;20496:419::-;20662:4;20700:2;20689:9;20685:18;20677:26;;20749:9;20743:4;20739:20;20735:1;20724:9;20720:17;20713:47;20777:131;20903:4;20777:131;:::i;:::-;20769:139;;20496:419;;;:::o;20921:188::-;20959:3;20978:18;20994:1;20978:18;:::i;:::-;20973:23;;21010:18;21026:1;21010:18;:::i;:::-;21005:23;;21051:1;21048;21044:9;21037:16;;21074:4;21069:3;21066:13;21063:39;;;21082:18;;:::i;:::-;21063:39;20921:188;;;;:::o;21115:141::-;21164:4;21187:3;21179:11;;21210:3;21207:1;21200:14;21244:4;21241:1;21231:18;21223:26;;21115:141;;;:::o;21262:93::-;21299:6;21346:2;21341;21334:5;21330:14;21326:23;21316:33;;21262:93;;;:::o;21361:107::-;21405:8;21455:5;21449:4;21445:16;21424:37;;21361:107;;;;:::o;21474:393::-;21543:6;21593:1;21581:10;21577:18;21616:97;21646:66;21635:9;21616:97;:::i;:::-;21734:39;21764:8;21753:9;21734:39;:::i;:::-;21722:51;;21806:4;21802:9;21795:5;21791:21;21782:30;;21855:4;21845:8;21841:19;21834:5;21831:30;21821:40;;21550:317;;21474:393;;;;;:::o;21873:60::-;21901:3;21922:5;21915:12;;21873:60;;;:::o;21939:142::-;21989:9;22022:53;22040:34;22049:24;22067:5;22049:24;:::i;:::-;22040:34;:::i;:::-;22022:53;:::i;:::-;22009:66;;21939:142;;;:::o;22087:75::-;22130:3;22151:5;22144:12;;22087:75;;;:::o;22168:269::-;22278:39;22309:7;22278:39;:::i;:::-;22339:91;22388:41;22412:16;22388:41;:::i;:::-;22380:6;22373:4;22367:11;22339:91;:::i;:::-;22333:4;22326:105;22244:193;22168:269;;;:::o;22443:73::-;22488:3;22443:73;:::o;22522:189::-;22599:32;;:::i;:::-;22640:65;22698:6;22690;22684:4;22640:65;:::i;:::-;22575:136;22522:189;;:::o;22717:186::-;22777:120;22794:3;22787:5;22784:14;22777:120;;;22848:39;22885:1;22878:5;22848:39;:::i;:::-;22821:1;22814:5;22810:13;22801:22;;22777:120;;;22717:186;;:::o;22909:543::-;23010:2;23005:3;23002:11;22999:446;;;23044:38;23076:5;23044:38;:::i;:::-;23128:29;23146:10;23128:29;:::i;:::-;23118:8;23114:44;23311:2;23299:10;23296:18;23293:49;;;23332:8;23317:23;;23293:49;23355:80;23411:22;23429:3;23411:22;:::i;:::-;23401:8;23397:37;23384:11;23355:80;:::i;:::-;23014:431;;22999:446;22909:543;;;:::o;23458:117::-;23512:8;23562:5;23556:4;23552:16;23531:37;;23458:117;;;;:::o;23581:169::-;23625:6;23658:51;23706:1;23702:6;23694:5;23691:1;23687:13;23658:51;:::i;:::-;23654:56;23739:4;23733;23729:15;23719:25;;23632:118;23581:169;;;;:::o;23755:295::-;23831:4;23977:29;24002:3;23996:4;23977:29;:::i;:::-;23969:37;;24039:3;24036:1;24032:11;24026:4;24023:21;24015:29;;23755:295;;;;:::o;24055:1395::-;24172:37;24205:3;24172:37;:::i;:::-;24274:18;24266:6;24263:30;24260:56;;;24296:18;;:::i;:::-;24260:56;24340:38;24372:4;24366:11;24340:38;:::i;:::-;24425:67;24485:6;24477;24471:4;24425:67;:::i;:::-;24519:1;24543:4;24530:17;;24575:2;24567:6;24564:14;24592:1;24587:618;;;;25249:1;25266:6;25263:77;;;25315:9;25310:3;25306:19;25300:26;25291:35;;25263:77;25366:67;25426:6;25419:5;25366:67;:::i;:::-;25360:4;25353:81;25222:222;24557:887;;24587:618;24639:4;24635:9;24627:6;24623:22;24673:37;24705:4;24673:37;:::i;:::-;24732:1;24746:208;24760:7;24757:1;24754:14;24746:208;;;24839:9;24834:3;24830:19;24824:26;24816:6;24809:42;24890:1;24882:6;24878:14;24868:24;;24937:2;24926:9;24922:18;24909:31;;24783:4;24780:1;24776:12;24771:17;;24746:208;;;24982:6;24973:7;24970:19;24967:179;;;25040:9;25035:3;25031:19;25025:26;25083:48;25125:4;25117:6;25113:17;25102:9;25083:48;:::i;:::-;25075:6;25068:64;24990:156;24967:179;25192:1;25188;25180:6;25176:14;25172:22;25166:4;25159:36;24594:611;;;24557:887;;24147:1303;;;24055:1395;;:::o;25456:229::-;25596:34;25592:1;25584:6;25580:14;25573:58;25665:12;25660:2;25652:6;25648:15;25641:37;25456:229;:::o;25691:366::-;25833:3;25854:67;25918:2;25913:3;25854:67;:::i;:::-;25847:74;;25930:93;26019:3;25930:93;:::i;:::-;26048:2;26043:3;26039:12;26032:19;;25691:366;;;:::o;26063:419::-;26229:4;26267:2;26256:9;26252:18;26244:26;;26316:9;26310:4;26306:20;26302:1;26291:9;26287:17;26280:47;26344:131;26470:4;26344:131;:::i;:::-;26336:139;;26063:419;;;:::o;26488:180::-;26536:77;26533:1;26526:88;26633:4;26630:1;26623:15;26657:4;26654:1;26647:15;26674:191;26712:4;26732:18;26748:1;26732:18;:::i;:::-;26727:23;;26764:18;26780:1;26764:18;:::i;:::-;26759:23;;26806:1;26803;26799:9;26791:17;;26830:4;26824;26821:14;26818:40;;;26838:18;;:::i;:::-;26818:40;26674:191;;;;:::o;26871:162::-;27011:14;27007:1;26999:6;26995:14;26988:38;26871:162;:::o;27039:366::-;27181:3;27202:67;27266:2;27261:3;27202:67;:::i;:::-;27195:74;;27278:93;27367:3;27278:93;:::i;:::-;27396:2;27391:3;27387:12;27380:19;;27039:366;;;:::o;27411:419::-;27577:4;27615:2;27604:9;27600:18;27592:26;;27664:9;27658:4;27654:20;27650:1;27639:9;27635:17;27628:47;27692:131;27818:4;27692:131;:::i;:::-;27684:139;;27411:419;;;:::o;27836:148::-;27938:11;27975:3;27960:18;;27836:148;;;;:::o;27990:390::-;28096:3;28124:39;28157:5;28124:39;:::i;:::-;28179:89;28261:6;28256:3;28179:89;:::i;:::-;28172:96;;28277:65;28335:6;28330:3;28323:4;28316:5;28312:16;28277:65;:::i;:::-;28367:6;28362:3;28358:16;28351:23;;28100:280;27990:390;;;;:::o;28386:435::-;28566:3;28588:95;28679:3;28670:6;28588:95;:::i;:::-;28581:102;;28700:95;28791:3;28782:6;28700:95;:::i;:::-;28693:102;;28812:3;28805:10;;28386:435;;;;;:::o;28827:79::-;28866:7;28895:5;28884:16;;28827:79;;;:::o;28912:157::-;29017:45;29037:24;29055:5;29037:24;:::i;:::-;29017:45;:::i;:::-;29012:3;29005:58;28912:157;;:::o;29075:397::-;29215:3;29230:75;29301:3;29292:6;29230:75;:::i;:::-;29330:2;29325:3;29321:12;29314:19;;29343:75;29414:3;29405:6;29343:75;:::i;:::-;29443:2;29438:3;29434:12;29427:19;;29463:3;29456:10;;29075:397;;;;;:::o;29478:171::-;29517:3;29540:24;29558:5;29540:24;:::i;:::-;29531:33;;29586:4;29579:5;29576:15;29573:41;;29594:18;;:::i;:::-;29573:41;29641:1;29634:5;29630:13;29623:20;;29478:171;;;:::o;29655:180::-;29703:77;29700:1;29693:88;29800:4;29797:1;29790:15;29824:4;29821:1;29814:15;29841:197;29880:3;29899:19;29916:1;29899:19;:::i;:::-;29894:24;;29932:19;29949:1;29932:19;:::i;:::-;29927:24;;29974:1;29971;29967:9;29960:16;;29997:10;29992:3;29989:19;29986:45;;;30011:18;;:::i;:::-;29986:45;29841:197;;;;:::o
Swarm Source
ipfs://b759f54012460361b42f3a4227bec927bf17ab62cd396622764adcd083861263
Loading...
Loading
Loading...
Loading
[ 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.