ERC-721
Source Code
Overview
Max Total Supply
1,692,600 BLHE
Holders
1,118,409
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 BLHELoading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
HeroNFT
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity)
/**
*Submitted for verification at basescan.org on 2024-05-30
*/
// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// 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/math/Math.sol
// 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/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/token/ERC721/IERC721Receiver.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/token/ERC721/IERC721.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
// 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/token/ERC721/ERC721.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
* the `spender` for the specific `tokenId`.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - 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 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
_checkOnERC721Received(address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` 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 _safeTransfer(address from, address to, uint256 tokenId) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
* recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC721InvalidReceiver(to);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.20;
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
* interfere with enumerability and should not be used together with `ERC721Enumerable`.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Burnable.sol)
pragma solidity ^0.8.20;
/**
* @title ERC721 Burnable Token
* @dev ERC721 Token that can be burned (destroyed).
*/
abstract contract ERC721Burnable is Context, ERC721 {
/**
* @dev Burns `tokenId`. See {ERC721-_burn}.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/
function burn(uint256 tokenId) public virtual {
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
_update(address(0), tokenId, _msgSender());
}
}
// 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: contracts/nfts/HeroNFT.sol
pragma solidity 0.8.24;
/**
* @title BLOCKLORDS
* @dev This contract provides functionality for minting, burning, and managing Blocklords Hero NFTs.
* @author BLOCKLORDS TEAM
* @notice ERC721 token contract representing the Blocklords Heroes (BLHE) token.
*/
contract HeroNFT is ERC721, ERC721Burnable, ERC721Enumerable, Ownable {
bool private lock; // Reentrancy guard
string private baseUri; // Base URI for token metadata
address public verifier; // Address of the verifier for signature verification
address private factory; // Address of the NFT Factory contract
mapping(address => uint256) public nonce; // Nonce for signature verification
event Minted(address indexed to, uint256 indexed tokenId, uint256 indexed time); // Event emitted when a new token is minted
event SetFactory(address indexed factory, uint256 indexed time); // Event emitted when the factory address is set
event SetVerifier(address indexed verifier, uint256 indexed time); // Event emitted when the verifier address is set
event Burned(address indexed owner, uint256 indexed tokenId, uint256 time); // Event emitted when a token is burned
/**
* @dev Constructor function to initialize the HeroNFT contract.
* @param initialOwner The address that will be set as the initial owner of the contract.
* @param _verifier The address of the verifier contract used for signature verification.
*/
constructor(address initialOwner, address _verifier) ERC721("Blocklords Heroes", "BLHE") Ownable(initialOwner) {
require(_verifier != address(0), "Verifier can't be zero address");
verifier = _verifier;
}
/**
* @dev Modifier to prevent reentrancy attacks.
*/
modifier nonReentrant() {
require(!lock, "No reentrant call");
lock = true;
_;
lock = false;
}
/**
* @dev Modifier to allow only the NFT Factory contract to call the method.
*/
modifier onlyFactory() {
require(factory == _msgSender(), "Only NFT factory can call the method");
_;
}
/**
* @dev Safely mints a new Hero NFT.
* @param _to Address to mint the token to.
* @param _tokenId ID of the token to mint.
* @param _deadline Expiry timestamp for the signature.
* @param _v ECDSA signature parameter v.
* @param _r ECDSA signature parameter r.
* @param _s ECDSA signature parameter s.
* @return The ID of the minted token.
*/
function safeMint(address _to, uint256 _tokenId, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s) external nonReentrant returns (uint256) {
require(_deadline >= block.timestamp, "Signature has expired");
{
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 message = keccak256(abi.encodePacked(_to, _tokenId, address(this), nonce[_to], _deadline, block.chainid));
bytes32 hash = keccak256(abi.encodePacked(prefix, message));
address recover = ecrecover(hash, _v, _r, _s);
require(recover == verifier, "Verification failed about mint hero nft");
}
nonce[_to]++;
_safeMint(_to, _tokenId);
emit Minted(_to, _tokenId, block.timestamp);
return _tokenId;
}
/**
* @dev Mints a new Hero NFT.
* @param _to Address to mint the token to.
* @param _tokenId ID of the token to mint.
* @return The ID of the minted token.
*/
function mint(address _to, uint256 _tokenId) external onlyFactory nonReentrant returns (uint256) {
nonce[_to]++;
_safeMint(_to, _tokenId);
emit Minted(_to, _tokenId, block.timestamp);
return _tokenId;
}
/**
* @dev Burns a Hero NFT.
* @param _tokenId ID of the token to burn.
*/
function burn(uint256 _tokenId) public override nonReentrant {
require(ownerOf(_tokenId) == msg.sender, "You are not the owner of this token");
_burn(_tokenId);
emit Burned(msg.sender, _tokenId, block.timestamp);
}
// Method called by the contract owner
/**
* @dev Sets the base URI for token metadata.
* @param _baseUri The base URI to set.
*/
function setBaseURI(string calldata _baseUri) external onlyOwner() {
baseUri = _baseUri;
}
/**
* @dev Sets the address of the verifier for signature verification.
* @param _verifier The address of the verifier contract.
*/
function setVerifier (address _verifier) external onlyOwner {
require(_verifier != address(0), "Verifier can't be zero address ");
verifier = _verifier;
emit SetVerifier(_verifier, block.timestamp);
}
/**
* @dev Sets the address of the NFT Factory contract.
* @param _factory The address of the NFT Factory contract.
*/
function setFactory(address _factory) public onlyOwner {
require(_factory != address(0), "Factory can't be zero address ");
factory = _factory;
emit SetFactory(_factory, block.timestamp);
}
// The following functions are overrides required by Solidity.
function _update(address to, uint256 tokenId, address auth) internal override(ERC721, ERC721Enumerable) returns (address) {
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value) internal override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, value);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _baseURI() internal view override returns (string memory) {
return baseUri;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"_verifier","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"time","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":"factory","type":"address"},{"indexed":true,"internalType":"uint256","name":"time","type":"uint256"}],"name":"SetFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"verifier","type":"address"},{"indexed":true,"internalType":"uint256","name":"time","type":"uint256"}],"name":"SetVerifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"safeMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseUri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifier","type":"address"}],"name":"setVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801562000010575f80fd5b50604051620042943803806200429483398181016040528101906200003691906200032e565b816040518060400160405280601181526020017f426c6f636b6c6f726473204865726f65730000000000000000000000000000008152506040518060400160405280600481526020017f424c484500000000000000000000000000000000000000000000000000000000815250815f9081620000b39190620005d7565b508060019081620000c59190620005d7565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200013b575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620001329190620006cc565b60405180910390fd5b6200014c816200020660201b60201c565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620001be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001b59062000745565b60405180910390fd5b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505062000765565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620002f882620002cd565b9050919050565b6200030a81620002ec565b811462000315575f80fd5b50565b5f815190506200032881620002ff565b92915050565b5f8060408385031215620003475762000346620002c9565b5b5f620003568582860162000318565b9250506020620003698582860162000318565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680620003ef57607f821691505b602082108103620004055762000404620003aa565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004697fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200042c565b6200047586836200042c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004bf620004b9620004b3846200048d565b62000496565b6200048d565b9050919050565b5f819050919050565b620004da836200049f565b620004f2620004e982620004c6565b84845462000438565b825550505050565b5f90565b62000508620004fa565b62000515818484620004cf565b505050565b5b818110156200053c57620005305f82620004fe565b6001810190506200051b565b5050565b601f8211156200058b5762000555816200040b565b62000560846200041d565b8101602085101562000570578190505b620005886200057f856200041d565b8301826200051a565b50505b505050565b5f82821c905092915050565b5f620005ad5f198460080262000590565b1980831691505092915050565b5f620005c783836200059c565b9150826002028217905092915050565b620005e28262000373565b67ffffffffffffffff811115620005fe57620005fd6200037d565b5b6200060a8254620003d7565b6200061782828562000540565b5f60209050601f8311600181146200064d575f841562000638578287015190505b620006448582620005ba565b865550620006b3565b601f1984166200065d866200040b565b5f5b8281101562000686578489015182556001820191506020850194506020810190506200065f565b86831015620006a65784890151620006a2601f8916826200059c565b8355505b6001600288020188555050505b505050505050565b620006c681620002ec565b82525050565b5f602082019050620006e15f830184620006bb565b92915050565b5f82825260208201905092915050565b7f56657269666965722063616e2774206265207a65726f206164647265737300005f82015250565b5f6200072d601e83620006e7565b91506200073a82620006f7565b602082019050919050565b5f6020820190508181035f8301526200075e816200071f565b9050919050565b613b2180620007735f395ff3fe608060405234801561000f575f80fd5b50600436106101a7575f3560e01c80635437988d116100f75780638da5cb5b11610095578063b88d4fde1161006f578063b88d4fde146104db578063c87b56dd146104f7578063e985e9c514610527578063f2fde38b14610557576101a7565b80638da5cb5b1461048357806395d89b41146104a1578063a22cb465146104bf576101a7565b80636352211e116100d15780636352211e146103e957806370a082311461041957806370ae92d214610449578063715018a614610479576101a7565b80635437988d1461039557806355f804b3146103b15780635bb47808146103cd576101a7565b80632b7ac3f31161016457806340c10f191161013e57806340c10f19146102fd57806342842e0e1461032d57806342966c68146103495780634f6ccce714610365576101a7565b80632b7ac3f31461027f5780632f745c591461029d57806338eff67f146102cd576101a7565b806301ffc9a7146101ab57806306fdde03146101db578063081812fc146101f9578063095ea7b31461022957806318160ddd1461024557806323b872dd14610263575b5f80fd5b6101c560048036038101906101c091906129a3565b610573565b6040516101d291906129e8565b60405180910390f35b6101e3610584565b6040516101f09190612a8b565b60405180910390f35b610213600480360381019061020e9190612ade565b610613565b6040516102209190612b48565b60405180910390f35b610243600480360381019061023e9190612b8b565b61062e565b005b61024d610644565b60405161025a9190612bd8565b60405180910390f35b61027d60048036038101906102789190612bf1565b610650565b005b61028761074f565b6040516102949190612b48565b60405180910390f35b6102b760048036038101906102b29190612b8b565b610774565b6040516102c49190612bd8565b60405180910390f35b6102e760048036038101906102e29190612caa565b610818565b6040516102f49190612bd8565b60405180910390f35b61031760048036038101906103129190612b8b565b610b47565b6040516103249190612bd8565b60405180910390f35b61034760048036038101906103429190612bf1565b610d0d565b005b610363600480360381019061035e9190612ade565b610d2c565b005b61037f600480360381019061037a9190612ade565b610e82565b60405161038c9190612bd8565b60405180910390f35b6103af60048036038101906103aa9190612d33565b610ef4565b005b6103cb60048036038101906103c69190612dbf565b610ff1565b005b6103e760048036038101906103e29190612d33565b61100f565b005b61040360048036038101906103fe9190612ade565b61110c565b6040516104109190612b48565b60405180910390f35b610433600480360381019061042e9190612d33565b61111d565b6040516104409190612bd8565b60405180910390f35b610463600480360381019061045e9190612d33565b6111d3565b6040516104709190612bd8565b60405180910390f35b6104816111e8565b005b61048b6111fb565b6040516104989190612b48565b60405180910390f35b6104a9611223565b6040516104b69190612a8b565b60405180910390f35b6104d960048036038101906104d49190612e34565b6112b3565b005b6104f560048036038101906104f09190612f9a565b6112c9565b005b610511600480360381019061050c9190612ade565b6112e6565b60405161051e9190612a8b565b60405180910390f35b610541600480360381019061053c919061301a565b61134c565b60405161054e91906129e8565b60405180910390f35b610571600480360381019061056c9190612d33565b6113da565b005b5f61057d8261145e565b9050919050565b60605f805461059290613085565b80601f01602080910402602001604051908101604052809291908181526020018280546105be90613085565b80156106095780601f106105e057610100808354040283529160200191610609565b820191905f5260205f20905b8154815290600101906020018083116105ec57829003601f168201915b5050505050905090565b5f61061d826114d7565b506106278261155d565b9050919050565b610640828261063b611596565b61159d565b5050565b5f600880549050905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106c0575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016106b79190612b48565b60405180910390fd5b5f6106d383836106ce611596565b6115af565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610749578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610740939291906130b5565b60405180910390fd5b50505050565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f61077e8361111d565b82106107c35782826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016107ba9291906130ea565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b5f600a60149054906101000a900460ff1615610869576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108609061315b565b60405180910390fd5b6001600a60146101000a81548160ff021916908315150217905550428510156108c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108be906131c3565b60405180910390fd5b5f6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090505f888830600e5f8d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20548a4660405160200161095996959493929190613246565b6040516020818303038152906040528051906020012090505f8282604051602001610985929190613319565b6040516020818303038152906040528051906020012090505f6001828989896040515f81526020016040526040516109c0949392919061335e565b6020604051602081039080840390855afa1580156109e0573d5f803e3d5ffd5b505050602060405103519050600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7290613411565b60405180910390fd5b50505050600e5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610acc9061345c565b9190505550610adb87876115c4565b42868873ffffffffffffffffffffffffffffffffffffffff167f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff60405160405180910390a48590505f600a60146101000a81548160ff0219169083151502179055509695505050505050565b5f610b50611596565b73ffffffffffffffffffffffffffffffffffffffff16600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610bde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd590613513565b60405180910390fd5b600a60149054906101000a900460ff1615610c2e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c259061315b565b60405180910390fd5b6001600a60146101000a81548160ff021916908315150217905550600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610c969061345c565b9190505550610ca583836115c4565b42828473ffffffffffffffffffffffffffffffffffffffff167f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff60405160405180910390a48190505f600a60146101000a81548160ff02191690831515021790555092915050565b610d2783838360405180602001604052805f8152506112c9565b505050565b600a60149054906101000a900460ff1615610d7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d739061315b565b60405180910390fd5b6001600a60146101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16610db78261110c565b73ffffffffffffffffffffffffffffffffffffffff1614610e0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e04906135a1565b60405180910390fd5b610e16816115e1565b803373ffffffffffffffffffffffffffffffffffffffff167f23ff0e75edf108e3d0392d92e13e8c8a868ef19001bd49f9e94876dc46dff87f42604051610e5d9190612bd8565b60405180910390a35f600a60146101000a81548160ff02191690831515021790555050565b5f610e8b610644565b8210610ed0575f826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610ec79291906130ea565b60405180910390fd5b60088281548110610ee457610ee36135bf565b5b905f5260205f2001549050919050565b610efc611663565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f6190613636565b60405180910390fd5b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428173ffffffffffffffffffffffffffffffffffffffff167feece16f4d5b3b30a740c6be8bd00ab16fb3774e49b182cba73a0a2b53b10c47060405160405180910390a350565b610ff9611663565b8181600b918261100a9291906137fb565b505050565b611017611663565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611085576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107c90613912565b60405180910390fd5b80600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428173ffffffffffffffffffffffffffffffffffffffff167f8d95e6b7f3e91dac5f4c8e6bd2ec031e14cb5c8699d0740a9bca228c989124ff60405160405180910390a350565b5f611116826114d7565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361118e575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016111859190612b48565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b600e602052805f5260405f205f915090505481565b6111f0611663565b6111f95f6116ea565b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461123290613085565b80601f016020809104026020016040519081016040528092919081815260200182805461125e90613085565b80156112a95780601f10611280576101008083540402835291602001916112a9565b820191905f5260205f20905b81548152906001019060200180831161128c57829003601f168201915b5050505050905090565b6112c56112be611596565b83836117ad565b5050565b6112d4848484610650565b6112e084848484611916565b50505050565b60606112f1826114d7565b505f6112fb611ac8565b90505f8151116113195760405180602001604052805f815250611344565b8061132384611b58565b60405160200161133492919061396a565b6040516020818303038152906040525b915050919050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6113e2611663565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611452575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016114499190612b48565b60405180910390fd5b61145b816116ea565b50565b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806114d057506114cf82611c22565b5b9050919050565b5f806114e283611d03565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361155457826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161154b9190612bd8565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6115aa8383836001611d3c565b505050565b5f6115bb848484611efb565b90509392505050565b6115dd828260405180602001604052805f815250612015565b5050565b5f6115ed5f835f6115af565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361165f57816040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016116569190612bd8565b60405180910390fd5b5050565b61166b611596565b73ffffffffffffffffffffffffffffffffffffffff166116896111fb565b73ffffffffffffffffffffffffffffffffffffffff16146116e8576116ac611596565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016116df9190612b48565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361181d57816040517f5b08ba180000000000000000000000000000000000000000000000000000000081526004016118149190612b48565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161190991906129e8565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611ac2578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02611959611596565b8685856040518563ffffffff1660e01b815260040161197b94939291906139d5565b6020604051808303815f875af19250505080156119b657506040513d601f19601f820116820180604052508101906119b39190613a33565b60015b611a37573d805f81146119e4576040519150601f19603f3d011682016040523d82523d5f602084013e6119e9565b606091505b505f815103611a2f57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611a269190612b48565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ac057836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611ab79190612b48565b60405180910390fd5b505b50505050565b6060600b8054611ad790613085565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0390613085565b8015611b4e5780601f10611b2557610100808354040283529160200191611b4e565b820191905f5260205f20905b815481529060010190602001808311611b3157829003601f168201915b5050505050905090565b60605f6001611b6684612030565b0190505f8167ffffffffffffffff811115611b8457611b83612e76565b5b6040519080825280601f01601f191660200182016040528015611bb65781602001600182028036833780820191505090505b5090505f82602001820190505b600115611c17578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611c0c57611c0b613a5e565b5b0494505f8503611bc3575b819350505050919050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611cec57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611cfc5750611cfb82612181565b5b9050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080611d7457505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15611ea6575f611d83846114d7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611ded57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015611e005750611dfe818461134c565b155b15611e4257826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401611e399190612b48565b60405180910390fd5b8115611ea457838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f80611f088585856121ea565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f4b57611f46846123f5565b611f8a565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611f8957611f888185612439565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611fcb57611fc684612583565b61200a565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612009576120088585612643565b5b5b809150509392505050565b61201f83836126c7565b61202b5f848484611916565b505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061208c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161208257612081613a5e565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106120c9576d04ee2d6d415b85acef810000000083816120bf576120be613a5e565b5b0492506020810190505b662386f26fc1000083106120f857662386f26fc1000083816120ee576120ed613a5e565b5b0492506010810190505b6305f5e1008310612121576305f5e100838161211757612116613a5e565b5b0492506008810190505b612710831061214657612710838161213c5761213b613a5e565b5b0492506004810190505b60648310612169576064838161215f5761215e613a5e565b5b0492506002810190505b600a8310612178576001810190505b80915050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f806121f584611d03565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612236576122358184866127ba565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146122c1576122755f855f80611d3c565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461234057600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6124438361111d565b90505f60075f8481526020019081526020015f2054905081811461251a575f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205490508060065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f20819055508160075f8381526020019081526020015f2081905550505b60075f8481526020019081526020015f205f905560065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f905550505050565b5f60016008805490506125969190613a8b565b90505f60095f8481526020019081526020015f205490505f600883815481106125c2576125c16135bf565b5b905f5260205f200154905080600883815481106125e2576125e16135bf565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f9055600880548061262a57612629613abe565b5b600190038181905f5260205f20015f9055905550505050565b5f600161264f8461111d565b6126599190613a8b565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612737575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161272e9190612b48565b60405180910390fd5b5f61274383835f6115af565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146127b5575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016127ac9190612b48565b60405180910390fd5b505050565b6127c583838361287d565b612878575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361283957806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016128309190612bd8565b60405180910390fd5b81816040517f177e802f00000000000000000000000000000000000000000000000000000000815260040161286f9291906130ea565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561293457508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806128f557506128f4848461134c565b5b8061293357508273ffffffffffffffffffffffffffffffffffffffff1661291b8361155d565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6129828161294e565b811461298c575f80fd5b50565b5f8135905061299d81612979565b92915050565b5f602082840312156129b8576129b7612946565b5b5f6129c58482850161298f565b91505092915050565b5f8115159050919050565b6129e2816129ce565b82525050565b5f6020820190506129fb5f8301846129d9565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015612a38578082015181840152602081019050612a1d565b5f8484015250505050565b5f601f19601f8301169050919050565b5f612a5d82612a01565b612a678185612a0b565b9350612a77818560208601612a1b565b612a8081612a43565b840191505092915050565b5f6020820190508181035f830152612aa38184612a53565b905092915050565b5f819050919050565b612abd81612aab565b8114612ac7575f80fd5b50565b5f81359050612ad881612ab4565b92915050565b5f60208284031215612af357612af2612946565b5b5f612b0084828501612aca565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612b3282612b09565b9050919050565b612b4281612b28565b82525050565b5f602082019050612b5b5f830184612b39565b92915050565b612b6a81612b28565b8114612b74575f80fd5b50565b5f81359050612b8581612b61565b92915050565b5f8060408385031215612ba157612ba0612946565b5b5f612bae85828601612b77565b9250506020612bbf85828601612aca565b9150509250929050565b612bd281612aab565b82525050565b5f602082019050612beb5f830184612bc9565b92915050565b5f805f60608486031215612c0857612c07612946565b5b5f612c1586828701612b77565b9350506020612c2686828701612b77565b9250506040612c3786828701612aca565b9150509250925092565b5f60ff82169050919050565b612c5681612c41565b8114612c60575f80fd5b50565b5f81359050612c7181612c4d565b92915050565b5f819050919050565b612c8981612c77565b8114612c93575f80fd5b50565b5f81359050612ca481612c80565b92915050565b5f805f805f8060c08789031215612cc457612cc3612946565b5b5f612cd189828a01612b77565b9650506020612ce289828a01612aca565b9550506040612cf389828a01612aca565b9450506060612d0489828a01612c63565b9350506080612d1589828a01612c96565b92505060a0612d2689828a01612c96565b9150509295509295509295565b5f60208284031215612d4857612d47612946565b5b5f612d5584828501612b77565b91505092915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112612d7f57612d7e612d5e565b5b8235905067ffffffffffffffff811115612d9c57612d9b612d62565b5b602083019150836001820283011115612db857612db7612d66565b5b9250929050565b5f8060208385031215612dd557612dd4612946565b5b5f83013567ffffffffffffffff811115612df257612df161294a565b5b612dfe85828601612d6a565b92509250509250929050565b612e13816129ce565b8114612e1d575f80fd5b50565b5f81359050612e2e81612e0a565b92915050565b5f8060408385031215612e4a57612e49612946565b5b5f612e5785828601612b77565b9250506020612e6885828601612e20565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612eac82612a43565b810181811067ffffffffffffffff82111715612ecb57612eca612e76565b5b80604052505050565b5f612edd61293d565b9050612ee98282612ea3565b919050565b5f67ffffffffffffffff821115612f0857612f07612e76565b5b612f1182612a43565b9050602081019050919050565b828183375f83830152505050565b5f612f3e612f3984612eee565b612ed4565b905082815260208101848484011115612f5a57612f59612e72565b5b612f65848285612f1e565b509392505050565b5f82601f830112612f8157612f80612d5e565b5b8135612f91848260208601612f2c565b91505092915050565b5f805f8060808587031215612fb257612fb1612946565b5b5f612fbf87828801612b77565b9450506020612fd087828801612b77565b9350506040612fe187828801612aca565b925050606085013567ffffffffffffffff8111156130025761300161294a565b5b61300e87828801612f6d565b91505092959194509250565b5f80604083850312156130305761302f612946565b5b5f61303d85828601612b77565b925050602061304e85828601612b77565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061309c57607f821691505b6020821081036130af576130ae613058565b5b50919050565b5f6060820190506130c85f830186612b39565b6130d56020830185612bc9565b6130e26040830184612b39565b949350505050565b5f6040820190506130fd5f830185612b39565b61310a6020830184612bc9565b9392505050565b7f4e6f207265656e7472616e742063616c6c0000000000000000000000000000005f82015250565b5f613145601183612a0b565b915061315082613111565b602082019050919050565b5f6020820190508181035f83015261317281613139565b9050919050565b7f5369676e617475726520686173206578706972656400000000000000000000005f82015250565b5f6131ad601583612a0b565b91506131b882613179565b602082019050919050565b5f6020820190508181035f8301526131da816131a1565b9050919050565b5f8160601b9050919050565b5f6131f7826131e1565b9050919050565b5f613208826131ed565b9050919050565b61322061321b82612b28565b6131fe565b82525050565b5f819050919050565b61324061323b82612aab565b613226565b82525050565b5f613251828961320f565b601482019150613261828861322f565b602082019150613271828761320f565b601482019150613281828661322f565b602082019150613291828561322f565b6020820191506132a1828461322f565b602082019150819050979650505050505050565b5f81519050919050565b5f81905092915050565b5f6132d3826132b5565b6132dd81856132bf565b93506132ed818560208601612a1b565b80840191505092915050565b5f819050919050565b61331361330e82612c77565b6132f9565b82525050565b5f61332482856132c9565b91506133308284613302565b6020820191508190509392505050565b61334981612c77565b82525050565b61335881612c41565b82525050565b5f6080820190506133715f830187613340565b61337e602083018661334f565b61338b6040830185613340565b6133986060830184613340565b95945050505050565b7f566572696669636174696f6e206661696c65642061626f7574206d696e7420685f8201527f65726f206e667400000000000000000000000000000000000000000000000000602082015250565b5f6133fb602783612a0b565b9150613406826133a1565b604082019050919050565b5f6020820190508181035f830152613428816133ef565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61346682612aab565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134985761349761342f565b5b600182019050919050565b7f4f6e6c79204e465420666163746f72792063616e2063616c6c20746865206d655f8201527f74686f6400000000000000000000000000000000000000000000000000000000602082015250565b5f6134fd602483612a0b565b9150613508826134a3565b604082019050919050565b5f6020820190508181035f83015261352a816134f1565b9050919050565b7f596f7520617265206e6f7420746865206f776e6572206f66207468697320746f5f8201527f6b656e0000000000000000000000000000000000000000000000000000000000602082015250565b5f61358b602383612a0b565b915061359682613531565b604082019050919050565b5f6020820190508181035f8301526135b88161357f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f56657269666965722063616e2774206265207a65726f206164647265737320005f82015250565b5f613620601f83612a0b565b915061362b826135ec565b602082019050919050565b5f6020820190508181035f83015261364d81613614565b9050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026136ba7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261367f565b6136c4868361367f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6136ff6136fa6136f584612aab565b6136dc565b612aab565b9050919050565b5f819050919050565b613718836136e5565b61372c61372482613706565b84845461368b565b825550505050565b5f90565b613740613734565b61374b81848461370f565b505050565b5b8181101561376e576137635f82613738565b600181019050613751565b5050565b601f8211156137b3576137848161365e565b61378d84613670565b8101602085101561379c578190505b6137b06137a885613670565b830182613750565b50505b505050565b5f82821c905092915050565b5f6137d35f19846008026137b8565b1980831691505092915050565b5f6137eb83836137c4565b9150826002028217905092915050565b6138058383613654565b67ffffffffffffffff81111561381e5761381d612e76565b5b6138288254613085565b613833828285613772565b5f601f831160018114613860575f841561384e578287013590505b61385885826137e0565b8655506138bf565b601f19841661386e8661365e565b5f5b8281101561389557848901358255600182019150602085019450602081019050613870565b868310156138b257848901356138ae601f8916826137c4565b8355505b6001600288020188555050505b50505050505050565b7f466163746f72792063616e2774206265207a65726f20616464726573732000005f82015250565b5f6138fc601e83612a0b565b9150613907826138c8565b602082019050919050565b5f6020820190508181035f830152613929816138f0565b9050919050565b5f81905092915050565b5f61394482612a01565b61394e8185613930565b935061395e818560208601612a1b565b80840191505092915050565b5f613975828561393a565b9150613981828461393a565b91508190509392505050565b5f82825260208201905092915050565b5f6139a7826132b5565b6139b1818561398d565b93506139c1818560208601612a1b565b6139ca81612a43565b840191505092915050565b5f6080820190506139e85f830187612b39565b6139f56020830186612b39565b613a026040830185612bc9565b8181036060830152613a14818461399d565b905095945050505050565b5f81519050613a2d81612979565b92915050565b5f60208284031215613a4857613a47612946565b5b5f613a5584828501613a1f565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613a9582612aab565b9150613aa083612aab565b9250828203905081811115613ab857613ab761342f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea26469706673582212208f99c872c67065b1dd30a7ccd318b5da6093ad2a9223bc08dd09fa5b3549f39f64736f6c63430008180033000000000000000000000000806c0485cfd1919f89a454effda3ef22a38544d60000000000000000000000009f8e636b6c22e6a457c8f535a818ad69914944bc
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101a7575f3560e01c80635437988d116100f75780638da5cb5b11610095578063b88d4fde1161006f578063b88d4fde146104db578063c87b56dd146104f7578063e985e9c514610527578063f2fde38b14610557576101a7565b80638da5cb5b1461048357806395d89b41146104a1578063a22cb465146104bf576101a7565b80636352211e116100d15780636352211e146103e957806370a082311461041957806370ae92d214610449578063715018a614610479576101a7565b80635437988d1461039557806355f804b3146103b15780635bb47808146103cd576101a7565b80632b7ac3f31161016457806340c10f191161013e57806340c10f19146102fd57806342842e0e1461032d57806342966c68146103495780634f6ccce714610365576101a7565b80632b7ac3f31461027f5780632f745c591461029d57806338eff67f146102cd576101a7565b806301ffc9a7146101ab57806306fdde03146101db578063081812fc146101f9578063095ea7b31461022957806318160ddd1461024557806323b872dd14610263575b5f80fd5b6101c560048036038101906101c091906129a3565b610573565b6040516101d291906129e8565b60405180910390f35b6101e3610584565b6040516101f09190612a8b565b60405180910390f35b610213600480360381019061020e9190612ade565b610613565b6040516102209190612b48565b60405180910390f35b610243600480360381019061023e9190612b8b565b61062e565b005b61024d610644565b60405161025a9190612bd8565b60405180910390f35b61027d60048036038101906102789190612bf1565b610650565b005b61028761074f565b6040516102949190612b48565b60405180910390f35b6102b760048036038101906102b29190612b8b565b610774565b6040516102c49190612bd8565b60405180910390f35b6102e760048036038101906102e29190612caa565b610818565b6040516102f49190612bd8565b60405180910390f35b61031760048036038101906103129190612b8b565b610b47565b6040516103249190612bd8565b60405180910390f35b61034760048036038101906103429190612bf1565b610d0d565b005b610363600480360381019061035e9190612ade565b610d2c565b005b61037f600480360381019061037a9190612ade565b610e82565b60405161038c9190612bd8565b60405180910390f35b6103af60048036038101906103aa9190612d33565b610ef4565b005b6103cb60048036038101906103c69190612dbf565b610ff1565b005b6103e760048036038101906103e29190612d33565b61100f565b005b61040360048036038101906103fe9190612ade565b61110c565b6040516104109190612b48565b60405180910390f35b610433600480360381019061042e9190612d33565b61111d565b6040516104409190612bd8565b60405180910390f35b610463600480360381019061045e9190612d33565b6111d3565b6040516104709190612bd8565b60405180910390f35b6104816111e8565b005b61048b6111fb565b6040516104989190612b48565b60405180910390f35b6104a9611223565b6040516104b69190612a8b565b60405180910390f35b6104d960048036038101906104d49190612e34565b6112b3565b005b6104f560048036038101906104f09190612f9a565b6112c9565b005b610511600480360381019061050c9190612ade565b6112e6565b60405161051e9190612a8b565b60405180910390f35b610541600480360381019061053c919061301a565b61134c565b60405161054e91906129e8565b60405180910390f35b610571600480360381019061056c9190612d33565b6113da565b005b5f61057d8261145e565b9050919050565b60605f805461059290613085565b80601f01602080910402602001604051908101604052809291908181526020018280546105be90613085565b80156106095780601f106105e057610100808354040283529160200191610609565b820191905f5260205f20905b8154815290600101906020018083116105ec57829003601f168201915b5050505050905090565b5f61061d826114d7565b506106278261155d565b9050919050565b610640828261063b611596565b61159d565b5050565b5f600880549050905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106c0575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016106b79190612b48565b60405180910390fd5b5f6106d383836106ce611596565b6115af565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610749578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610740939291906130b5565b60405180910390fd5b50505050565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f61077e8361111d565b82106107c35782826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016107ba9291906130ea565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b5f600a60149054906101000a900460ff1615610869576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108609061315b565b60405180910390fd5b6001600a60146101000a81548160ff021916908315150217905550428510156108c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108be906131c3565b60405180910390fd5b5f6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090505f888830600e5f8d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20548a4660405160200161095996959493929190613246565b6040516020818303038152906040528051906020012090505f8282604051602001610985929190613319565b6040516020818303038152906040528051906020012090505f6001828989896040515f81526020016040526040516109c0949392919061335e565b6020604051602081039080840390855afa1580156109e0573d5f803e3d5ffd5b505050602060405103519050600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7290613411565b60405180910390fd5b50505050600e5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610acc9061345c565b9190505550610adb87876115c4565b42868873ffffffffffffffffffffffffffffffffffffffff167f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff60405160405180910390a48590505f600a60146101000a81548160ff0219169083151502179055509695505050505050565b5f610b50611596565b73ffffffffffffffffffffffffffffffffffffffff16600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610bde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd590613513565b60405180910390fd5b600a60149054906101000a900460ff1615610c2e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c259061315b565b60405180910390fd5b6001600a60146101000a81548160ff021916908315150217905550600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610c969061345c565b9190505550610ca583836115c4565b42828473ffffffffffffffffffffffffffffffffffffffff167f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff60405160405180910390a48190505f600a60146101000a81548160ff02191690831515021790555092915050565b610d2783838360405180602001604052805f8152506112c9565b505050565b600a60149054906101000a900460ff1615610d7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d739061315b565b60405180910390fd5b6001600a60146101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16610db78261110c565b73ffffffffffffffffffffffffffffffffffffffff1614610e0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e04906135a1565b60405180910390fd5b610e16816115e1565b803373ffffffffffffffffffffffffffffffffffffffff167f23ff0e75edf108e3d0392d92e13e8c8a868ef19001bd49f9e94876dc46dff87f42604051610e5d9190612bd8565b60405180910390a35f600a60146101000a81548160ff02191690831515021790555050565b5f610e8b610644565b8210610ed0575f826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610ec79291906130ea565b60405180910390fd5b60088281548110610ee457610ee36135bf565b5b905f5260205f2001549050919050565b610efc611663565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f6190613636565b60405180910390fd5b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428173ffffffffffffffffffffffffffffffffffffffff167feece16f4d5b3b30a740c6be8bd00ab16fb3774e49b182cba73a0a2b53b10c47060405160405180910390a350565b610ff9611663565b8181600b918261100a9291906137fb565b505050565b611017611663565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611085576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107c90613912565b60405180910390fd5b80600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428173ffffffffffffffffffffffffffffffffffffffff167f8d95e6b7f3e91dac5f4c8e6bd2ec031e14cb5c8699d0740a9bca228c989124ff60405160405180910390a350565b5f611116826114d7565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361118e575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016111859190612b48565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b600e602052805f5260405f205f915090505481565b6111f0611663565b6111f95f6116ea565b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461123290613085565b80601f016020809104026020016040519081016040528092919081815260200182805461125e90613085565b80156112a95780601f10611280576101008083540402835291602001916112a9565b820191905f5260205f20905b81548152906001019060200180831161128c57829003601f168201915b5050505050905090565b6112c56112be611596565b83836117ad565b5050565b6112d4848484610650565b6112e084848484611916565b50505050565b60606112f1826114d7565b505f6112fb611ac8565b90505f8151116113195760405180602001604052805f815250611344565b8061132384611b58565b60405160200161133492919061396a565b6040516020818303038152906040525b915050919050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6113e2611663565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611452575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016114499190612b48565b60405180910390fd5b61145b816116ea565b50565b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806114d057506114cf82611c22565b5b9050919050565b5f806114e283611d03565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361155457826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161154b9190612bd8565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6115aa8383836001611d3c565b505050565b5f6115bb848484611efb565b90509392505050565b6115dd828260405180602001604052805f815250612015565b5050565b5f6115ed5f835f6115af565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361165f57816040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016116569190612bd8565b60405180910390fd5b5050565b61166b611596565b73ffffffffffffffffffffffffffffffffffffffff166116896111fb565b73ffffffffffffffffffffffffffffffffffffffff16146116e8576116ac611596565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016116df9190612b48565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361181d57816040517f5b08ba180000000000000000000000000000000000000000000000000000000081526004016118149190612b48565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161190991906129e8565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611ac2578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02611959611596565b8685856040518563ffffffff1660e01b815260040161197b94939291906139d5565b6020604051808303815f875af19250505080156119b657506040513d601f19601f820116820180604052508101906119b39190613a33565b60015b611a37573d805f81146119e4576040519150601f19603f3d011682016040523d82523d5f602084013e6119e9565b606091505b505f815103611a2f57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611a269190612b48565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ac057836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611ab79190612b48565b60405180910390fd5b505b50505050565b6060600b8054611ad790613085565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0390613085565b8015611b4e5780601f10611b2557610100808354040283529160200191611b4e565b820191905f5260205f20905b815481529060010190602001808311611b3157829003601f168201915b5050505050905090565b60605f6001611b6684612030565b0190505f8167ffffffffffffffff811115611b8457611b83612e76565b5b6040519080825280601f01601f191660200182016040528015611bb65781602001600182028036833780820191505090505b5090505f82602001820190505b600115611c17578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611c0c57611c0b613a5e565b5b0494505f8503611bc3575b819350505050919050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611cec57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611cfc5750611cfb82612181565b5b9050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080611d7457505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15611ea6575f611d83846114d7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611ded57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015611e005750611dfe818461134c565b155b15611e4257826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401611e399190612b48565b60405180910390fd5b8115611ea457838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f80611f088585856121ea565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f4b57611f46846123f5565b611f8a565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611f8957611f888185612439565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611fcb57611fc684612583565b61200a565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612009576120088585612643565b5b5b809150509392505050565b61201f83836126c7565b61202b5f848484611916565b505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061208c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161208257612081613a5e565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106120c9576d04ee2d6d415b85acef810000000083816120bf576120be613a5e565b5b0492506020810190505b662386f26fc1000083106120f857662386f26fc1000083816120ee576120ed613a5e565b5b0492506010810190505b6305f5e1008310612121576305f5e100838161211757612116613a5e565b5b0492506008810190505b612710831061214657612710838161213c5761213b613a5e565b5b0492506004810190505b60648310612169576064838161215f5761215e613a5e565b5b0492506002810190505b600a8310612178576001810190505b80915050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f806121f584611d03565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612236576122358184866127ba565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146122c1576122755f855f80611d3c565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461234057600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6124438361111d565b90505f60075f8481526020019081526020015f2054905081811461251a575f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205490508060065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f20819055508160075f8381526020019081526020015f2081905550505b60075f8481526020019081526020015f205f905560065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f905550505050565b5f60016008805490506125969190613a8b565b90505f60095f8481526020019081526020015f205490505f600883815481106125c2576125c16135bf565b5b905f5260205f200154905080600883815481106125e2576125e16135bf565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f9055600880548061262a57612629613abe565b5b600190038181905f5260205f20015f9055905550505050565b5f600161264f8461111d565b6126599190613a8b565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612737575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161272e9190612b48565b60405180910390fd5b5f61274383835f6115af565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146127b5575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016127ac9190612b48565b60405180910390fd5b505050565b6127c583838361287d565b612878575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361283957806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016128309190612bd8565b60405180910390fd5b81816040517f177e802f00000000000000000000000000000000000000000000000000000000815260040161286f9291906130ea565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561293457508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806128f557506128f4848461134c565b5b8061293357508273ffffffffffffffffffffffffffffffffffffffff1661291b8361155d565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6129828161294e565b811461298c575f80fd5b50565b5f8135905061299d81612979565b92915050565b5f602082840312156129b8576129b7612946565b5b5f6129c58482850161298f565b91505092915050565b5f8115159050919050565b6129e2816129ce565b82525050565b5f6020820190506129fb5f8301846129d9565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015612a38578082015181840152602081019050612a1d565b5f8484015250505050565b5f601f19601f8301169050919050565b5f612a5d82612a01565b612a678185612a0b565b9350612a77818560208601612a1b565b612a8081612a43565b840191505092915050565b5f6020820190508181035f830152612aa38184612a53565b905092915050565b5f819050919050565b612abd81612aab565b8114612ac7575f80fd5b50565b5f81359050612ad881612ab4565b92915050565b5f60208284031215612af357612af2612946565b5b5f612b0084828501612aca565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612b3282612b09565b9050919050565b612b4281612b28565b82525050565b5f602082019050612b5b5f830184612b39565b92915050565b612b6a81612b28565b8114612b74575f80fd5b50565b5f81359050612b8581612b61565b92915050565b5f8060408385031215612ba157612ba0612946565b5b5f612bae85828601612b77565b9250506020612bbf85828601612aca565b9150509250929050565b612bd281612aab565b82525050565b5f602082019050612beb5f830184612bc9565b92915050565b5f805f60608486031215612c0857612c07612946565b5b5f612c1586828701612b77565b9350506020612c2686828701612b77565b9250506040612c3786828701612aca565b9150509250925092565b5f60ff82169050919050565b612c5681612c41565b8114612c60575f80fd5b50565b5f81359050612c7181612c4d565b92915050565b5f819050919050565b612c8981612c77565b8114612c93575f80fd5b50565b5f81359050612ca481612c80565b92915050565b5f805f805f8060c08789031215612cc457612cc3612946565b5b5f612cd189828a01612b77565b9650506020612ce289828a01612aca565b9550506040612cf389828a01612aca565b9450506060612d0489828a01612c63565b9350506080612d1589828a01612c96565b92505060a0612d2689828a01612c96565b9150509295509295509295565b5f60208284031215612d4857612d47612946565b5b5f612d5584828501612b77565b91505092915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112612d7f57612d7e612d5e565b5b8235905067ffffffffffffffff811115612d9c57612d9b612d62565b5b602083019150836001820283011115612db857612db7612d66565b5b9250929050565b5f8060208385031215612dd557612dd4612946565b5b5f83013567ffffffffffffffff811115612df257612df161294a565b5b612dfe85828601612d6a565b92509250509250929050565b612e13816129ce565b8114612e1d575f80fd5b50565b5f81359050612e2e81612e0a565b92915050565b5f8060408385031215612e4a57612e49612946565b5b5f612e5785828601612b77565b9250506020612e6885828601612e20565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612eac82612a43565b810181811067ffffffffffffffff82111715612ecb57612eca612e76565b5b80604052505050565b5f612edd61293d565b9050612ee98282612ea3565b919050565b5f67ffffffffffffffff821115612f0857612f07612e76565b5b612f1182612a43565b9050602081019050919050565b828183375f83830152505050565b5f612f3e612f3984612eee565b612ed4565b905082815260208101848484011115612f5a57612f59612e72565b5b612f65848285612f1e565b509392505050565b5f82601f830112612f8157612f80612d5e565b5b8135612f91848260208601612f2c565b91505092915050565b5f805f8060808587031215612fb257612fb1612946565b5b5f612fbf87828801612b77565b9450506020612fd087828801612b77565b9350506040612fe187828801612aca565b925050606085013567ffffffffffffffff8111156130025761300161294a565b5b61300e87828801612f6d565b91505092959194509250565b5f80604083850312156130305761302f612946565b5b5f61303d85828601612b77565b925050602061304e85828601612b77565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061309c57607f821691505b6020821081036130af576130ae613058565b5b50919050565b5f6060820190506130c85f830186612b39565b6130d56020830185612bc9565b6130e26040830184612b39565b949350505050565b5f6040820190506130fd5f830185612b39565b61310a6020830184612bc9565b9392505050565b7f4e6f207265656e7472616e742063616c6c0000000000000000000000000000005f82015250565b5f613145601183612a0b565b915061315082613111565b602082019050919050565b5f6020820190508181035f83015261317281613139565b9050919050565b7f5369676e617475726520686173206578706972656400000000000000000000005f82015250565b5f6131ad601583612a0b565b91506131b882613179565b602082019050919050565b5f6020820190508181035f8301526131da816131a1565b9050919050565b5f8160601b9050919050565b5f6131f7826131e1565b9050919050565b5f613208826131ed565b9050919050565b61322061321b82612b28565b6131fe565b82525050565b5f819050919050565b61324061323b82612aab565b613226565b82525050565b5f613251828961320f565b601482019150613261828861322f565b602082019150613271828761320f565b601482019150613281828661322f565b602082019150613291828561322f565b6020820191506132a1828461322f565b602082019150819050979650505050505050565b5f81519050919050565b5f81905092915050565b5f6132d3826132b5565b6132dd81856132bf565b93506132ed818560208601612a1b565b80840191505092915050565b5f819050919050565b61331361330e82612c77565b6132f9565b82525050565b5f61332482856132c9565b91506133308284613302565b6020820191508190509392505050565b61334981612c77565b82525050565b61335881612c41565b82525050565b5f6080820190506133715f830187613340565b61337e602083018661334f565b61338b6040830185613340565b6133986060830184613340565b95945050505050565b7f566572696669636174696f6e206661696c65642061626f7574206d696e7420685f8201527f65726f206e667400000000000000000000000000000000000000000000000000602082015250565b5f6133fb602783612a0b565b9150613406826133a1565b604082019050919050565b5f6020820190508181035f830152613428816133ef565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61346682612aab565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134985761349761342f565b5b600182019050919050565b7f4f6e6c79204e465420666163746f72792063616e2063616c6c20746865206d655f8201527f74686f6400000000000000000000000000000000000000000000000000000000602082015250565b5f6134fd602483612a0b565b9150613508826134a3565b604082019050919050565b5f6020820190508181035f83015261352a816134f1565b9050919050565b7f596f7520617265206e6f7420746865206f776e6572206f66207468697320746f5f8201527f6b656e0000000000000000000000000000000000000000000000000000000000602082015250565b5f61358b602383612a0b565b915061359682613531565b604082019050919050565b5f6020820190508181035f8301526135b88161357f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f56657269666965722063616e2774206265207a65726f206164647265737320005f82015250565b5f613620601f83612a0b565b915061362b826135ec565b602082019050919050565b5f6020820190508181035f83015261364d81613614565b9050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026136ba7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261367f565b6136c4868361367f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6136ff6136fa6136f584612aab565b6136dc565b612aab565b9050919050565b5f819050919050565b613718836136e5565b61372c61372482613706565b84845461368b565b825550505050565b5f90565b613740613734565b61374b81848461370f565b505050565b5b8181101561376e576137635f82613738565b600181019050613751565b5050565b601f8211156137b3576137848161365e565b61378d84613670565b8101602085101561379c578190505b6137b06137a885613670565b830182613750565b50505b505050565b5f82821c905092915050565b5f6137d35f19846008026137b8565b1980831691505092915050565b5f6137eb83836137c4565b9150826002028217905092915050565b6138058383613654565b67ffffffffffffffff81111561381e5761381d612e76565b5b6138288254613085565b613833828285613772565b5f601f831160018114613860575f841561384e578287013590505b61385885826137e0565b8655506138bf565b601f19841661386e8661365e565b5f5b8281101561389557848901358255600182019150602085019450602081019050613870565b868310156138b257848901356138ae601f8916826137c4565b8355505b6001600288020188555050505b50505050505050565b7f466163746f72792063616e2774206265207a65726f20616464726573732000005f82015250565b5f6138fc601e83612a0b565b9150613907826138c8565b602082019050919050565b5f6020820190508181035f830152613929816138f0565b9050919050565b5f81905092915050565b5f61394482612a01565b61394e8185613930565b935061395e818560208601612a1b565b80840191505092915050565b5f613975828561393a565b9150613981828461393a565b91508190509392505050565b5f82825260208201905092915050565b5f6139a7826132b5565b6139b1818561398d565b93506139c1818560208601612a1b565b6139ca81612a43565b840191505092915050565b5f6080820190506139e85f830187612b39565b6139f56020830186612b39565b613a026040830185612bc9565b8181036060830152613a14818461399d565b905095945050505050565b5f81519050613a2d81612979565b92915050565b5f60208284031215613a4857613a47612946565b5b5f613a5584828501613a1f565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613a9582612aab565b9150613aa083612aab565b9250828203905081811115613ab857613ab761342f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea26469706673582212208f99c872c67065b1dd30a7ccd318b5da6093ad2a9223bc08dd09fa5b3549f39f64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000806c0485cfd1919f89a454effda3ef22a38544d60000000000000000000000009f8e636b6c22e6a457c8f535a818ad69914944bc
-----Decoded View---------------
Arg [0] : initialOwner (address): 0x806c0485cFd1919f89A454EFFDA3eF22a38544D6
Arg [1] : _verifier (address): 0x9f8E636b6c22e6A457C8f535A818AD69914944bc
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000806c0485cfd1919f89a454effda3ef22a38544d6
Arg [1] : 0000000000000000000000009f8e636b6c22e6a457c8f535a818ad69914944bc
Deployed Bytecode Sourcemap
67191:5790:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72699:171;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;39724:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40896:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40715:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;57480:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41565:588;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;67395:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;57144:260;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;69559:851;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70617:260;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;42224:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;70983:248;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;57661:231;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;71664:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71397:104;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72048:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;39537:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;39262:213;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;67564:40;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;66032:103;;;:::i;:::-;;65357:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;39884:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41126:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;42429:211;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;40050:260;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41343:155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;66290:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72699:171;72802:4;72826:36;72850:11;72826:23;:36::i;:::-;72819:43;;72699:171;;;:::o;39724:91::-;39769:13;39802:5;39795:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39724:91;:::o;40896:158::-;40963:7;40983:22;40997:7;40983:13;:22::i;:::-;;41025:21;41038:7;41025:12;:21::i;:::-;41018:28;;40896:158;;;:::o;40715:115::-;40787:35;40796:2;40800:7;40809:12;:10;:12::i;:::-;40787:8;:35::i;:::-;40715:115;;:::o;57480:104::-;57532:7;57559:10;:17;;;;57552:24;;57480:104;:::o;41565:588::-;41674:1;41660:16;;:2;:16;;;41656:89;;41730:1;41700:33;;;;;;;;;;;:::i;:::-;;;;;;;;41656:89;41966:21;41990:34;41998:2;42002:7;42011:12;:10;:12::i;:::-;41990:7;:34::i;:::-;41966:58;;42056:4;42039:21;;:13;:21;;;42035:111;;42105:4;42111:7;42120:13;42084:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;42035:111;41645:508;41565:588;;;:::o;67395:24::-;;;;;;;;;;;;;:::o;57144:260::-;57232:7;57265:16;57275:5;57265:9;:16::i;:::-;57256:5;:25;57252:101;;57328:5;57335;57305:36;;;;;;;;;;;;:::i;:::-;;;;;;;;57252:101;57370:12;:19;57383:5;57370:19;;;;;;;;;;;;;;;:26;57390:5;57370:26;;;;;;;;;;;;57363:33;;57144:260;;;;:::o;69559:851::-;69692:7;68819:4;;;;;;;;;;;68818:5;68810:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;68863:4;68856;;:11;;;;;;;;;;;;;;;;;;69733:15:::1;69720:9;:28;;69712:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;69802:19;:60;;;;;;;;;;;;;;;;::::0;::::1;;69877:15;69930:3;69935:8;69953:4;69960:5;:10;69966:3;69960:10;;;;;;;;;;;;;;;;69972:9;69983:13;69913:84;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;69903:95;;;;;;69877:121;;70013:12;70066:6;70074:7;70049:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;70039:44;;;;;;70013:70;;70098:15;70124:27;70134:4;70140:2;70144;70148;70124:27;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;70098:53;;70187:8;;;;;;;;;;;70176:19;;:7;:19;;;70168:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;69787:464;;;;70263:5;:10;70269:3;70263:10;;;;;;;;;;;;;;;;:12;;;;;;;;;:::i;:::-;;;;;;70288:24;70298:3;70303:8;70288:9;:24::i;:::-;70360:15;70350:8;70345:3;70338:38;;;;;;;;;;;;70394:8;70387:15;;68897:5:::0;68890:4;;:12;;;;;;;;;;;;;;;;;;69559:851;;;;;;;;:::o;70617:260::-;70705:7;69070:12;:10;:12::i;:::-;69059:23;;:7;;;;;;;;;;;:23;;;69051:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;68819:4:::1;;;;;;;;;;;68818:5;68810:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;68863:4;68856;;:11;;;;;;;;;;;;;;;;;;70730:5:::2;:10;70736:3;70730:10;;;;;;;;;;;;;;;;:12;;;;;;;;;:::i;:::-;;;;;;70755:24;70765:3;70770:8;70755:9;:24::i;:::-;70827:15;70817:8;70812:3;70805:38;;;;;;;;;;;;70861:8;70854:15;;68897:5:::1;68890:4;;:12;;;;;;;;;;;;;;;;;;70617:260:::0;;;;:::o;42224:134::-;42311:39;42328:4;42334:2;42338:7;42311:39;;;;;;;;;;;;:16;:39::i;:::-;42224:134;;;:::o;70983:248::-;68819:4;;;;;;;;;;;68818:5;68810:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;68863:4;68856;;:11;;;;;;;;;;;;;;;;;;71084:10:::1;71063:31;;:17;71071:8;71063:7;:17::i;:::-;:31;;;71055:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;71145:15;71151:8;71145:5;:15::i;:::-;71197:8;71185:10;71178:45;;;71207:15;71178:45;;;;;;:::i;:::-;;;;;;;;68897:5:::0;68890:4;;:12;;;;;;;;;;;;;;;;;;70983:248;:::o;57661:231::-;57727:7;57760:13;:11;:13::i;:::-;57751:5;:22;57747:103;;57828:1;57832:5;57797:41;;;;;;;;;;;;:::i;:::-;;;;;;;;57747:103;57867:10;57878:5;57867:17;;;;;;;;:::i;:::-;;;;;;;;;;57860:24;;57661:231;;;:::o;71664:234::-;65243:13;:11;:13::i;:::-;71764:1:::1;71743:23;;:9;:23;;::::0;71735:67:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;71824:9;71813:8;;:20;;;;;;;;;;;;;;;;;;71874:15;71863:9;71851:39;;;;;;;;;;;;71664:234:::0;:::o;71397:104::-;65243:13;:11;:13::i;:::-;71485:8:::1;;71475:7;:18;;;;;;;:::i;:::-;;71397:104:::0;;:::o;72048:220::-;65243:13;:11;:13::i;:::-;72142:1:::1;72122:22;;:8;:22;;::::0;72114:65:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;72197:8;72187:7;;:18;;;;;;;;;;;;;;;;;;72244:15;72234:8;72223:37;;;;;;;;;;;;72048:220:::0;:::o;39537:120::-;39600:7;39627:22;39641:7;39627:13;:22::i;:::-;39620:29;;39537:120;;;:::o;39262:213::-;39325:7;39366:1;39349:19;;:5;:19;;;39345:89;;39419:1;39392:30;;;;;;;;;;;:::i;:::-;;;;;;;;39345:89;39451:9;:16;39461:5;39451:16;;;;;;;;;;;;;;;;39444:23;;39262:213;;;:::o;67564:40::-;;;;;;;;;;;;;;;;;:::o;66032:103::-;65243:13;:11;:13::i;:::-;66097:30:::1;66124:1;66097:18;:30::i;:::-;66032:103::o:0;65357:87::-;65403:7;65430:6;;;;;;;;;;;65423:13;;65357:87;:::o;39884:95::-;39931:13;39964:7;39957:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39884:95;:::o;41126:146::-;41212:52;41231:12;:10;:12::i;:::-;41245:8;41255;41212:18;:52::i;:::-;41126:146;;:::o;42429:211::-;42543:31;42556:4;42562:2;42566:7;42543:12;:31::i;:::-;42585:47;42608:4;42614:2;42618:7;42627:4;42585:22;:47::i;:::-;42429:211;;;;:::o;40050:260::-;40114:13;40140:22;40154:7;40140:13;:22::i;:::-;;40175:21;40199:10;:8;:10::i;:::-;40175:34;;40251:1;40233:7;40227:21;:25;:75;;;;;;;;;;;;;;;;;40269:7;40278:18;:7;:16;:18::i;:::-;40255:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;40227:75;40220:82;;;40050:260;;;:::o;41343:155::-;41431:4;41455:18;:25;41474:5;41455:25;;;;;;;;;;;;;;;:35;41481:8;41455:35;;;;;;;;;;;;;;;;;;;;;;;;;41448:42;;41343:155;;;;:::o;66290:220::-;65243:13;:11;:13::i;:::-;66395:1:::1;66375:22;;:8;:22;;::::0;66371:93:::1;;66449:1;66421:31;;;;;;;;;;;:::i;:::-;;;;;;;;66371:93;66474:28;66493:8;66474:18;:28::i;:::-;66290:220:::0;:::o;56836:224::-;56938:4;56977:35;56962:50;;;:11;:50;;;;:90;;;;57016:36;57040:11;57016:23;:36::i;:::-;56962:90;56955:97;;56836:224;;;:::o;53871:247::-;53934:7;53954:13;53970:17;53979:7;53970:8;:17::i;:::-;53954:33;;54019:1;54002:19;;:5;:19;;;53998:90;;54068:7;54045:31;;;;;;;;;;;:::i;:::-;;;;;;;;53998:90;54105:5;54098:12;;;53871:247;;;:::o;43402:129::-;43472:7;43499:15;:24;43515:7;43499:24;;;;;;;;;;;;;;;;;;;;;43492:31;;43402:129;;;:::o;37326:98::-;37379:7;37406:10;37399:17;;37326:98;:::o;52103:122::-;52184:33;52193:2;52197:7;52206:4;52212;52184:8;:33::i;:::-;52103:122;;;:::o;72344:180::-;72457:7;72484:32;72498:2;72502:7;72511:4;72484:13;:32::i;:::-;72477:39;;72344:180;;;;;:::o;48222:102::-;48290:26;48300:2;48304:7;48290:26;;;;;;;;;;;;:9;:26::i;:::-;48222:102;;:::o;49075:232::-;49127:21;49151:40;49167:1;49171:7;49188:1;49151:7;:40::i;:::-;49127:64;;49231:1;49206:27;;:13;:27;;;49202:98;;49280:7;49257:31;;;;;;;;;;;:::i;:::-;;;;;;;;49202:98;49116:191;49075:232;:::o;65522:166::-;65593:12;:10;:12::i;:::-;65582:23;;:7;:5;:7::i;:::-;:23;;;65578:103;;65656:12;:10;:12::i;:::-;65629:40;;;;;;;;;;;:::i;:::-;;;;;;;;65578:103;65522:166::o;66670:191::-;66744:16;66763:6;;;;;;;;;;;66744:25;;66789:8;66780:6;;:17;;;;;;;;;;;;;;;;;;66844:8;66813:40;;66834:8;66813:40;;;;;;;;;;;;66733:128;66670:191;:::o;53310:318::-;53438:1;53418:22;;:8;:22;;;53414:93;;53486:8;53464:31;;;;;;;;;;;:::i;:::-;;;;;;;;53414:93;53555:8;53517:18;:25;53536:5;53517:25;;;;;;;;;;;;;;;:35;53543:8;53517:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;53601:8;53579:41;;53594:5;53579:41;;;53611:8;53579:41;;;;;;:::i;:::-;;;;;;;;53310:318;;;:::o;54668:799::-;54802:1;54785:2;:14;;;:18;54781:679;;;54840:2;54824:36;;;54861:12;:10;:12::i;:::-;54875:4;54881:7;54890:4;54824:71;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;54820:629;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55155:1;55138:6;:13;:18;55134:300;;55210:2;55188:25;;;;;;;;;;;:::i;:::-;;;;;;;;55134:300;55384:6;55378:13;55369:6;55365:2;55361:15;55354:38;54820:629;54953:41;;;54943:51;;;:6;:51;;;;54939:132;;55048:2;55026:25;;;;;;;;;;;:::i;:::-;;;;;;;;54939:132;54896:190;54781:679;54668:799;;;;:::o;72878:100::-;72930:13;72963:7;72956:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72878:100;:::o;24225:718::-;24281:13;24332:14;24369:1;24349:17;24360:5;24349:10;:17::i;:::-;:21;24332:38;;24385:20;24419:6;24408:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24385:41;;24441:11;24570:6;24566:2;24562:15;24554:6;24550:28;24543:35;;24607:290;24614:4;24607:290;;;24639:5;;;;;;;;24781:10;24776:2;24769:5;24765:14;24760:32;24755:3;24747:46;24839:2;24830:11;;;;;;:::i;:::-;;;;;24873:1;24864:5;:10;24607:290;24860:21;24607:290;24918:6;24911:13;;;;;24225:718;;;:::o;38893:305::-;38995:4;39047:25;39032:40;;;:11;:40;;;;:105;;;;39104:33;39089:48;;;:11;:48;;;;39032:105;:158;;;;39154:36;39178:11;39154:23;:36::i;:::-;39032:158;39012:178;;38893:305;;;:::o;43164:117::-;43230:7;43257;:16;43265:7;43257:16;;;;;;;;;;;;;;;;;;;;;43250:23;;43164:117;;;:::o;52413:678::-;52575:9;:31;;;;52604:1;52588:18;;:4;:18;;;;52575:31;52571:471;;;52623:13;52639:22;52653:7;52639:13;:22::i;:::-;52623:38;;52808:1;52792:18;;:4;:18;;;;:35;;;;;52823:4;52814:13;;:5;:13;;;;52792:35;:69;;;;;52832:29;52849:5;52856:4;52832:16;:29::i;:::-;52831:30;52792:69;52788:144;;;52911:4;52889:27;;;;;;;;;;;:::i;:::-;;;;;;;;52788:144;52952:9;52948:83;;;53007:7;53003:2;52987:28;;52996:5;52987:28;;;;;;;;;;;;52948:83;52608:434;52571:471;53081:2;53054:15;:24;53070:7;53054:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;52413:678;;;;:::o;57953:640::-;58048:7;58068:21;58092:32;58106:2;58110:7;58119:4;58092:13;:32::i;:::-;58068:56;;58166:1;58141:27;;:13;:27;;;58137:214;;58185:40;58217:7;58185:31;:40::i;:::-;58137:214;;;58264:2;58247:19;;:13;:19;;;58243:108;;58283:56;58316:13;58331:7;58283:32;:56::i;:::-;58243:108;58137:214;58379:1;58365:16;;:2;:16;;;58361:192;;58398:45;58435:7;58398:36;:45::i;:::-;58361:192;;;58482:2;58465:19;;:13;:19;;;58461:92;;58501:40;58529:2;58533:7;58501:27;:40::i;:::-;58461:92;58361:192;58572:13;58565:20;;;57953:640;;;;;:::o;48551:185::-;48646:18;48652:2;48656:7;48646:5;:18::i;:::-;48675:53;48706:1;48710:2;48714:7;48723:4;48675:22;:53::i;:::-;48551:185;;;:::o;20629:948::-;20682:7;20702:14;20719:1;20702:18;;20769:8;20760:5;:17;20756:106;;20807:8;20798:17;;;;;;:::i;:::-;;;;;20844:2;20834:12;;;;20756:106;20889:8;20880:5;:17;20876:106;;20927:8;20918:17;;;;;;:::i;:::-;;;;;20964:2;20954:12;;;;20876:106;21009:8;21000:5;:17;20996:106;;21047:8;21038:17;;;;;;:::i;:::-;;;;;21084:2;21074:12;;;;20996:106;21129:7;21120:5;:16;21116:103;;21166:7;21157:16;;;;;;:::i;:::-;;;;;21202:1;21192:11;;;;21116:103;21246:7;21237:5;:16;21233:103;;21283:7;21274:16;;;;;;:::i;:::-;;;;;21319:1;21309:11;;;;21233:103;21363:7;21354:5;:16;21350:103;;21400:7;21391:16;;;;;;:::i;:::-;;;;;21436:1;21426:11;;;;21350:103;21480:7;21471:5;:16;21467:68;;21518:1;21508:11;;;;21467:68;21563:6;21556:13;;;20629:948;;;:::o;29537:148::-;29613:4;29652:25;29637:40;;;:11;:40;;;;29630:47;;29537:148;;;:::o;46364:824::-;46450:7;46470:12;46485:17;46494:7;46485:8;:17::i;:::-;46470:32;;46581:1;46565:18;;:4;:18;;;46561:88;;46600:37;46617:4;46623;46629:7;46600:16;:37::i;:::-;46561:88;46712:1;46696:18;;:4;:18;;;46692:263;;46814:48;46831:1;46835:7;46852:1;46856:5;46814:8;:48::i;:::-;46927:1;46908:9;:15;46918:4;46908:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;46692:263;46985:1;46971:16;;:2;:16;;;46967:111;;47050:1;47033:9;:13;47043:2;47033:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;46967:111;47109:2;47090:7;:16;47098:7;47090:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;47148:7;47144:2;47129:27;;47138:4;47129:27;;;;;;;;;;;;47176:4;47169:11;;;46364:824;;;;;:::o;59313:164::-;59417:10;:17;;;;59390:15;:24;59406:7;59390:24;;;;;;;;;;;:44;;;;59445:10;59461:7;59445:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59313:164;:::o;60104:977::-;60370:22;60395:15;60405:4;60395:9;:15::i;:::-;60370:40;;60421:18;60442:17;:26;60460:7;60442:26;;;;;;;;;;;;60421:47;;60589:14;60575:10;:28;60571:328;;60620:19;60642:12;:18;60655:4;60642:18;;;;;;;;;;;;;;;:34;60661:14;60642:34;;;;;;;;;;;;60620:56;;60726:11;60693:12;:18;60706:4;60693:18;;;;;;;;;;;;;;;:30;60712:10;60693:30;;;;;;;;;;;:44;;;;60843:10;60810:17;:30;60828:11;60810:30;;;;;;;;;;;:43;;;;60605:294;60571:328;60995:17;:26;61013:7;60995:26;;;;;;;;;;;60988:33;;;61039:12;:18;61052:4;61039:18;;;;;;;;;;;;;;;:34;61058:14;61039:34;;;;;;;;;;;61032:41;;;60185:896;;60104:977;;:::o;61376:1079::-;61629:22;61674:1;61654:10;:17;;;;:21;;;;:::i;:::-;61629:46;;61686:18;61707:15;:24;61723:7;61707:24;;;;;;;;;;;;61686:45;;62058:19;62080:10;62091:14;62080:26;;;;;;;;:::i;:::-;;;;;;;;;;62058:48;;62144:11;62119:10;62130;62119:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;62255:10;62224:15;:28;62240:11;62224:28;;;;;;;;;;;:41;;;;62396:15;:24;62412:7;62396:24;;;;;;;;;;;62389:31;;;62431:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;61447:1008;;;61376:1079;:::o;58894:218::-;58979:14;59012:1;58996:13;59006:2;58996:9;:13::i;:::-;:17;;;;:::i;:::-;58979:34;;59051:7;59024:12;:16;59037:2;59024:16;;;;;;;;;;;;;;;:24;59041:6;59024:24;;;;;;;;;;;:34;;;;59098:6;59069:17;:26;59087:7;59069:26;;;;;;;;;;;:35;;;;58968:144;58894:218;;:::o;47524:335::-;47606:1;47592:16;;:2;:16;;;47588:89;;47662:1;47632:33;;;;;;;;;;;:::i;:::-;;;;;;;;47588:89;47687:21;47711:32;47719:2;47723:7;47740:1;47711:7;:32::i;:::-;47687:56;;47783:1;47758:27;;:13;:27;;;47754:98;;47837:1;47809:31;;;;;;;;;;;:::i;:::-;;;;;;;;47754:98;47577:282;47524:335;;:::o;44571:376::-;44684:38;44698:5;44705:7;44714;44684:13;:38::i;:::-;44679:261;;44760:1;44743:19;;:5;:19;;;44739:190;;44813:7;44790:31;;;;;;;;;;;:::i;:::-;;;;;;;;44739:190;44896:7;44905;44869:44;;;;;;;;;;;;:::i;:::-;;;;;;;;44679:261;44571:376;;;:::o;43851:276::-;43954:4;44010:1;43991:21;;:7;:21;;;;:128;;;;;44039:7;44030:16;;:5;:16;;;:52;;;;44050:32;44067:5;44074:7;44050:16;:32::i;:::-;44030:52;:88;;;;44111:7;44086:32;;:21;44099:7;44086:12;:21::i;:::-;:32;;;44030:88;43991:128;43971:148;;43851:276;;;;;:::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:77::-;6261:7;6290:5;6279:16;;6224:77;;;:::o;6307:122::-;6380:24;6398:5;6380:24;:::i;:::-;6373:5;6370:35;6360:63;;6419:1;6416;6409:12;6360:63;6307:122;:::o;6435:139::-;6481:5;6519:6;6506:20;6497:29;;6535:33;6562:5;6535:33;:::i;:::-;6435:139;;;;:::o;6580:1053::-;6682:6;6690;6698;6706;6714;6722;6771:3;6759:9;6750:7;6746:23;6742:33;6739:120;;;6778:79;;:::i;:::-;6739:120;6898:1;6923:53;6968:7;6959:6;6948:9;6944:22;6923:53;:::i;:::-;6913:63;;6869:117;7025:2;7051:53;7096:7;7087:6;7076:9;7072:22;7051:53;:::i;:::-;7041:63;;6996:118;7153:2;7179:53;7224:7;7215:6;7204:9;7200:22;7179:53;:::i;:::-;7169:63;;7124:118;7281:2;7307:51;7350:7;7341:6;7330:9;7326:22;7307:51;:::i;:::-;7297:61;;7252:116;7407:3;7434:53;7479:7;7470:6;7459:9;7455:22;7434:53;:::i;:::-;7424:63;;7378:119;7536:3;7563:53;7608:7;7599:6;7588:9;7584:22;7563:53;:::i;:::-;7553:63;;7507:119;6580:1053;;;;;;;;:::o;7639:329::-;7698:6;7747:2;7735:9;7726:7;7722:23;7718:32;7715:119;;;7753:79;;:::i;:::-;7715:119;7873:1;7898:53;7943:7;7934:6;7923:9;7919:22;7898:53;:::i;:::-;7888:63;;7844:117;7639:329;;;;:::o;7974:117::-;8083:1;8080;8073:12;8097:117;8206:1;8203;8196:12;8220:117;8329:1;8326;8319:12;8357:553;8415:8;8425:6;8475:3;8468:4;8460:6;8456:17;8452:27;8442:122;;8483:79;;:::i;:::-;8442:122;8596:6;8583:20;8573:30;;8626:18;8618:6;8615:30;8612:117;;;8648:79;;:::i;:::-;8612:117;8762:4;8754:6;8750:17;8738:29;;8816:3;8808:4;8800:6;8796:17;8786:8;8782:32;8779:41;8776:128;;;8823:79;;:::i;:::-;8776:128;8357:553;;;;;:::o;8916:529::-;8987:6;8995;9044:2;9032:9;9023:7;9019:23;9015:32;9012:119;;;9050:79;;:::i;:::-;9012:119;9198:1;9187:9;9183:17;9170:31;9228:18;9220:6;9217:30;9214:117;;;9250:79;;:::i;:::-;9214:117;9363:65;9420:7;9411:6;9400:9;9396:22;9363:65;:::i;:::-;9345:83;;;;9141:297;8916:529;;;;;:::o;9451:116::-;9521:21;9536:5;9521:21;:::i;:::-;9514:5;9511:32;9501:60;;9557:1;9554;9547:12;9501:60;9451:116;:::o;9573:133::-;9616:5;9654:6;9641:20;9632:29;;9670:30;9694:5;9670:30;:::i;:::-;9573:133;;;;:::o;9712:468::-;9777:6;9785;9834:2;9822:9;9813:7;9809:23;9805:32;9802:119;;;9840:79;;:::i;:::-;9802:119;9960:1;9985:53;10030:7;10021:6;10010:9;10006:22;9985:53;:::i;:::-;9975:63;;9931:117;10087:2;10113:50;10155:7;10146:6;10135:9;10131:22;10113:50;:::i;:::-;10103:60;;10058:115;9712:468;;;;;:::o;10186:117::-;10295:1;10292;10285:12;10309:180;10357:77;10354:1;10347:88;10454:4;10451:1;10444:15;10478:4;10475:1;10468:15;10495:281;10578:27;10600:4;10578:27;:::i;:::-;10570:6;10566:40;10708:6;10696:10;10693:22;10672:18;10660:10;10657:34;10654:62;10651:88;;;10719:18;;:::i;:::-;10651:88;10759:10;10755:2;10748:22;10538:238;10495:281;;:::o;10782:129::-;10816:6;10843:20;;:::i;:::-;10833:30;;10872:33;10900:4;10892:6;10872:33;:::i;:::-;10782:129;;;:::o;10917:307::-;10978:4;11068:18;11060:6;11057:30;11054:56;;;11090:18;;:::i;:::-;11054:56;11128:29;11150:6;11128:29;:::i;:::-;11120:37;;11212:4;11206;11202:15;11194:23;;10917:307;;;:::o;11230:146::-;11327:6;11322:3;11317;11304:30;11368:1;11359:6;11354:3;11350:16;11343:27;11230:146;;;:::o;11382:423::-;11459:5;11484:65;11500:48;11541:6;11500:48;:::i;:::-;11484:65;:::i;:::-;11475:74;;11572:6;11565:5;11558:21;11610:4;11603:5;11599:16;11648:3;11639:6;11634:3;11630:16;11627:25;11624:112;;;11655:79;;:::i;:::-;11624:112;11745:54;11792:6;11787:3;11782;11745:54;:::i;:::-;11465:340;11382:423;;;;;:::o;11824:338::-;11879:5;11928:3;11921:4;11913:6;11909:17;11905:27;11895:122;;11936:79;;:::i;:::-;11895:122;12053:6;12040:20;12078:78;12152:3;12144:6;12137:4;12129:6;12125:17;12078:78;:::i;:::-;12069:87;;11885:277;11824:338;;;;:::o;12168:943::-;12263:6;12271;12279;12287;12336:3;12324:9;12315:7;12311:23;12307:33;12304:120;;;12343:79;;:::i;:::-;12304:120;12463:1;12488:53;12533:7;12524:6;12513:9;12509:22;12488:53;:::i;:::-;12478:63;;12434:117;12590:2;12616:53;12661:7;12652:6;12641:9;12637:22;12616:53;:::i;:::-;12606:63;;12561:118;12718:2;12744:53;12789:7;12780:6;12769:9;12765:22;12744:53;:::i;:::-;12734:63;;12689:118;12874:2;12863:9;12859:18;12846:32;12905:18;12897:6;12894:30;12891:117;;;12927:79;;:::i;:::-;12891:117;13032:62;13086:7;13077:6;13066:9;13062:22;13032:62;:::i;:::-;13022:72;;12817:287;12168:943;;;;;;;:::o;13117:474::-;13185:6;13193;13242:2;13230:9;13221:7;13217:23;13213:32;13210:119;;;13248:79;;:::i;:::-;13210:119;13368:1;13393:53;13438:7;13429:6;13418:9;13414:22;13393:53;:::i;:::-;13383:63;;13339:117;13495:2;13521:53;13566:7;13557:6;13546:9;13542:22;13521:53;:::i;:::-;13511:63;;13466:118;13117:474;;;;;:::o;13597:180::-;13645:77;13642:1;13635:88;13742:4;13739:1;13732:15;13766:4;13763:1;13756:15;13783:320;13827:6;13864:1;13858:4;13854:12;13844:22;;13911:1;13905:4;13901:12;13932:18;13922:81;;13988:4;13980:6;13976:17;13966:27;;13922:81;14050:2;14042:6;14039:14;14019:18;14016:38;14013:84;;14069:18;;:::i;:::-;14013:84;13834:269;13783:320;;;:::o;14109:442::-;14258:4;14296:2;14285:9;14281:18;14273:26;;14309:71;14377:1;14366:9;14362:17;14353:6;14309:71;:::i;:::-;14390:72;14458:2;14447:9;14443:18;14434:6;14390:72;:::i;:::-;14472;14540:2;14529:9;14525:18;14516:6;14472:72;:::i;:::-;14109:442;;;;;;:::o;14557:332::-;14678:4;14716:2;14705:9;14701:18;14693:26;;14729:71;14797:1;14786:9;14782:17;14773:6;14729:71;:::i;:::-;14810:72;14878:2;14867:9;14863:18;14854:6;14810:72;:::i;:::-;14557:332;;;;;:::o;14895:167::-;15035:19;15031:1;15023:6;15019:14;15012:43;14895:167;:::o;15068:366::-;15210:3;15231:67;15295:2;15290:3;15231:67;:::i;:::-;15224:74;;15307:93;15396:3;15307:93;:::i;:::-;15425:2;15420:3;15416:12;15409:19;;15068:366;;;:::o;15440:419::-;15606:4;15644:2;15633:9;15629:18;15621:26;;15693:9;15687:4;15683:20;15679:1;15668:9;15664:17;15657:47;15721:131;15847:4;15721:131;:::i;:::-;15713:139;;15440:419;;;:::o;15865:171::-;16005:23;16001:1;15993:6;15989:14;15982:47;15865:171;:::o;16042:366::-;16184:3;16205:67;16269:2;16264:3;16205:67;:::i;:::-;16198:74;;16281:93;16370:3;16281:93;:::i;:::-;16399:2;16394:3;16390:12;16383:19;;16042:366;;;:::o;16414:419::-;16580:4;16618:2;16607:9;16603:18;16595:26;;16667:9;16661:4;16657:20;16653:1;16642:9;16638:17;16631:47;16695:131;16821:4;16695:131;:::i;:::-;16687:139;;16414:419;;;:::o;16839:94::-;16872:8;16920:5;16916:2;16912:14;16891:35;;16839:94;;;:::o;16939:::-;16978:7;17007:20;17021:5;17007:20;:::i;:::-;16996:31;;16939:94;;;:::o;17039:100::-;17078:7;17107:26;17127:5;17107:26;:::i;:::-;17096:37;;17039:100;;;:::o;17145:157::-;17250:45;17270:24;17288:5;17270:24;:::i;:::-;17250:45;:::i;:::-;17245:3;17238:58;17145:157;;:::o;17308:79::-;17347:7;17376:5;17365:16;;17308:79;;;:::o;17393:157::-;17498:45;17518:24;17536:5;17518:24;:::i;:::-;17498:45;:::i;:::-;17493:3;17486:58;17393:157;;:::o;17556:961::-;17808:3;17823:75;17894:3;17885:6;17823:75;:::i;:::-;17923:2;17918:3;17914:12;17907:19;;17936:75;18007:3;17998:6;17936:75;:::i;:::-;18036:2;18031:3;18027:12;18020:19;;18049:75;18120:3;18111:6;18049:75;:::i;:::-;18149:2;18144:3;18140:12;18133:19;;18162:75;18233:3;18224:6;18162:75;:::i;:::-;18262:2;18257:3;18253:12;18246:19;;18275:75;18346:3;18337:6;18275:75;:::i;:::-;18375:2;18370:3;18366:12;18359:19;;18388:75;18459:3;18450:6;18388:75;:::i;:::-;18488:2;18483:3;18479:12;18472:19;;18508:3;18501:10;;17556:961;;;;;;;;;:::o;18523:98::-;18574:6;18608:5;18602:12;18592:22;;18523:98;;;:::o;18627:147::-;18728:11;18765:3;18750:18;;18627:147;;;;:::o;18780:386::-;18884:3;18912:38;18944:5;18912:38;:::i;:::-;18966:88;19047:6;19042:3;18966:88;:::i;:::-;18959:95;;19063:65;19121:6;19116:3;19109:4;19102:5;19098:16;19063:65;:::i;:::-;19153:6;19148:3;19144:16;19137:23;;18888:278;18780:386;;;;:::o;19172:79::-;19211:7;19240:5;19229:16;;19172:79;;;:::o;19257:157::-;19362:45;19382:24;19400:5;19382:24;:::i;:::-;19362:45;:::i;:::-;19357:3;19350:58;19257:157;;:::o;19420:412::-;19578:3;19600:93;19689:3;19680:6;19600:93;:::i;:::-;19593:100;;19703:75;19774:3;19765:6;19703:75;:::i;:::-;19803:2;19798:3;19794:12;19787:19;;19823:3;19816:10;;19420:412;;;;;:::o;19838:118::-;19925:24;19943:5;19925:24;:::i;:::-;19920:3;19913:37;19838:118;;:::o;19962:112::-;20045:22;20061:5;20045:22;:::i;:::-;20040:3;20033:35;19962:112;;:::o;20080:545::-;20253:4;20291:3;20280:9;20276:19;20268:27;;20305:71;20373:1;20362:9;20358:17;20349:6;20305:71;:::i;:::-;20386:68;20450:2;20439:9;20435:18;20426:6;20386:68;:::i;:::-;20464:72;20532:2;20521:9;20517:18;20508:6;20464:72;:::i;:::-;20546;20614:2;20603:9;20599:18;20590:6;20546:72;:::i;:::-;20080:545;;;;;;;:::o;20631:226::-;20771:34;20767:1;20759:6;20755:14;20748:58;20840:9;20835:2;20827:6;20823:15;20816:34;20631:226;:::o;20863:366::-;21005:3;21026:67;21090:2;21085:3;21026:67;:::i;:::-;21019:74;;21102:93;21191:3;21102:93;:::i;:::-;21220:2;21215:3;21211:12;21204:19;;20863:366;;;:::o;21235:419::-;21401:4;21439:2;21428:9;21424:18;21416:26;;21488:9;21482:4;21478:20;21474:1;21463:9;21459:17;21452:47;21516:131;21642:4;21516:131;:::i;:::-;21508:139;;21235:419;;;:::o;21660:180::-;21708:77;21705:1;21698:88;21805:4;21802:1;21795:15;21829:4;21826:1;21819:15;21846:233;21885:3;21908:24;21926:5;21908:24;:::i;:::-;21899:33;;21954:66;21947:5;21944:77;21941:103;;22024:18;;:::i;:::-;21941:103;22071:1;22064:5;22060:13;22053:20;;21846:233;;;:::o;22085:223::-;22225:34;22221:1;22213:6;22209:14;22202:58;22294:6;22289:2;22281:6;22277:15;22270:31;22085:223;:::o;22314:366::-;22456:3;22477:67;22541:2;22536:3;22477:67;:::i;:::-;22470:74;;22553:93;22642:3;22553:93;:::i;:::-;22671:2;22666:3;22662:12;22655:19;;22314:366;;;:::o;22686:419::-;22852:4;22890:2;22879:9;22875:18;22867:26;;22939:9;22933:4;22929:20;22925:1;22914:9;22910:17;22903:47;22967:131;23093:4;22967:131;:::i;:::-;22959:139;;22686:419;;;:::o;23111:222::-;23251:34;23247:1;23239:6;23235:14;23228:58;23320:5;23315:2;23307:6;23303:15;23296:30;23111:222;:::o;23339:366::-;23481:3;23502:67;23566:2;23561:3;23502:67;:::i;:::-;23495:74;;23578:93;23667:3;23578:93;:::i;:::-;23696:2;23691:3;23687:12;23680:19;;23339:366;;;:::o;23711:419::-;23877:4;23915:2;23904:9;23900:18;23892:26;;23964:9;23958:4;23954:20;23950:1;23939:9;23935:17;23928:47;23992:131;24118:4;23992:131;:::i;:::-;23984:139;;23711:419;;;:::o;24136:180::-;24184:77;24181:1;24174:88;24281:4;24278:1;24271:15;24305:4;24302:1;24295:15;24322:181;24462:33;24458:1;24450:6;24446:14;24439:57;24322:181;:::o;24509:366::-;24651:3;24672:67;24736:2;24731:3;24672:67;:::i;:::-;24665:74;;24748:93;24837:3;24748:93;:::i;:::-;24866:2;24861:3;24857:12;24850:19;;24509:366;;;:::o;24881:419::-;25047:4;25085:2;25074:9;25070:18;25062:26;;25134:9;25128:4;25124:20;25120:1;25109:9;25105:17;25098:47;25162:131;25288:4;25162:131;:::i;:::-;25154:139;;24881:419;;;:::o;25306:97::-;25365:6;25393:3;25383:13;;25306:97;;;;:::o;25409:141::-;25458:4;25481:3;25473:11;;25504:3;25501:1;25494:14;25538:4;25535:1;25525:18;25517:26;;25409:141;;;:::o;25556:93::-;25593:6;25640:2;25635;25628:5;25624:14;25620:23;25610:33;;25556:93;;;:::o;25655:107::-;25699:8;25749:5;25743:4;25739:16;25718:37;;25655:107;;;;:::o;25768:393::-;25837:6;25887:1;25875:10;25871:18;25910:97;25940:66;25929:9;25910:97;:::i;:::-;26028:39;26058:8;26047:9;26028:39;:::i;:::-;26016:51;;26100:4;26096:9;26089:5;26085:21;26076:30;;26149:4;26139:8;26135:19;26128:5;26125:30;26115:40;;25844:317;;25768:393;;;;;:::o;26167:60::-;26195:3;26216:5;26209:12;;26167:60;;;:::o;26233:142::-;26283:9;26316:53;26334:34;26343:24;26361:5;26343:24;:::i;:::-;26334:34;:::i;:::-;26316:53;:::i;:::-;26303:66;;26233:142;;;:::o;26381:75::-;26424:3;26445:5;26438:12;;26381:75;;;:::o;26462:269::-;26572:39;26603:7;26572:39;:::i;:::-;26633:91;26682:41;26706:16;26682:41;:::i;:::-;26674:6;26667:4;26661:11;26633:91;:::i;:::-;26627:4;26620:105;26538:193;26462:269;;;:::o;26737:73::-;26782:3;26737:73;:::o;26816:189::-;26893:32;;:::i;:::-;26934:65;26992:6;26984;26978:4;26934:65;:::i;:::-;26869:136;26816:189;;:::o;27011:186::-;27071:120;27088:3;27081:5;27078:14;27071:120;;;27142:39;27179:1;27172:5;27142:39;:::i;:::-;27115:1;27108:5;27104:13;27095:22;;27071:120;;;27011:186;;:::o;27203:543::-;27304:2;27299:3;27296:11;27293:446;;;27338:38;27370:5;27338:38;:::i;:::-;27422:29;27440:10;27422:29;:::i;:::-;27412:8;27408:44;27605:2;27593:10;27590:18;27587:49;;;27626:8;27611:23;;27587:49;27649:80;27705:22;27723:3;27705:22;:::i;:::-;27695:8;27691:37;27678:11;27649:80;:::i;:::-;27308:431;;27293:446;27203:543;;;:::o;27752:117::-;27806:8;27856:5;27850:4;27846:16;27825:37;;27752:117;;;;:::o;27875:169::-;27919:6;27952:51;28000:1;27996:6;27988:5;27985:1;27981:13;27952:51;:::i;:::-;27948:56;28033:4;28027;28023:15;28013:25;;27926:118;27875:169;;;;:::o;28049:295::-;28125:4;28271:29;28296:3;28290:4;28271:29;:::i;:::-;28263:37;;28333:3;28330:1;28326:11;28320:4;28317:21;28309:29;;28049:295;;;;:::o;28349:1403::-;28473:44;28513:3;28508;28473:44;:::i;:::-;28582:18;28574:6;28571:30;28568:56;;;28604:18;;:::i;:::-;28568:56;28648:38;28680:4;28674:11;28648:38;:::i;:::-;28733:67;28793:6;28785;28779:4;28733:67;:::i;:::-;28827:1;28856:2;28848:6;28845:14;28873:1;28868:632;;;;29544:1;29561:6;29558:84;;;29617:9;29612:3;29608:19;29595:33;29586:42;;29558:84;29668:67;29728:6;29721:5;29668:67;:::i;:::-;29662:4;29655:81;29517:229;28838:908;;28868:632;28920:4;28916:9;28908:6;28904:22;28954:37;28986:4;28954:37;:::i;:::-;29013:1;29027:215;29041:7;29038:1;29035:14;29027:215;;;29127:9;29122:3;29118:19;29105:33;29097:6;29090:49;29178:1;29170:6;29166:14;29156:24;;29225:2;29214:9;29210:18;29197:31;;29064:4;29061:1;29057:12;29052:17;;29027:215;;;29270:6;29261:7;29258:19;29255:186;;;29335:9;29330:3;29326:19;29313:33;29378:48;29420:4;29412:6;29408:17;29397:9;29378:48;:::i;:::-;29370:6;29363:64;29278:163;29255:186;29487:1;29483;29475:6;29471:14;29467:22;29461:4;29454:36;28875:625;;;28838:908;;28448:1304;;;28349:1403;;;:::o;29758:180::-;29898:32;29894:1;29886:6;29882:14;29875:56;29758:180;:::o;29944:366::-;30086:3;30107:67;30171:2;30166:3;30107:67;:::i;:::-;30100:74;;30183:93;30272:3;30183:93;:::i;:::-;30301:2;30296:3;30292:12;30285:19;;29944:366;;;:::o;30316:419::-;30482:4;30520:2;30509:9;30505:18;30497:26;;30569:9;30563:4;30559:20;30555:1;30544:9;30540:17;30533:47;30597:131;30723:4;30597:131;:::i;:::-;30589:139;;30316:419;;;:::o;30741:148::-;30843:11;30880:3;30865:18;;30741:148;;;;:::o;30895:390::-;31001:3;31029:39;31062:5;31029:39;:::i;:::-;31084:89;31166:6;31161:3;31084:89;:::i;:::-;31077:96;;31182:65;31240:6;31235:3;31228:4;31221:5;31217:16;31182:65;:::i;:::-;31272:6;31267:3;31263:16;31256:23;;31005:280;30895:390;;;;:::o;31291:435::-;31471:3;31493:95;31584:3;31575:6;31493:95;:::i;:::-;31486:102;;31605:95;31696:3;31687:6;31605:95;:::i;:::-;31598:102;;31717:3;31710:10;;31291:435;;;;;:::o;31732:168::-;31815:11;31849:6;31844:3;31837:19;31889:4;31884:3;31880:14;31865:29;;31732:168;;;;:::o;31906:373::-;31992:3;32020:38;32052:5;32020:38;:::i;:::-;32074:70;32137:6;32132:3;32074:70;:::i;:::-;32067:77;;32153:65;32211:6;32206:3;32199:4;32192:5;32188:16;32153:65;:::i;:::-;32243:29;32265:6;32243:29;:::i;:::-;32238:3;32234:39;32227:46;;31996:283;31906:373;;;;:::o;32285:640::-;32480:4;32518:3;32507:9;32503:19;32495:27;;32532:71;32600:1;32589:9;32585:17;32576:6;32532:71;:::i;:::-;32613:72;32681:2;32670:9;32666:18;32657:6;32613:72;:::i;:::-;32695;32763:2;32752:9;32748:18;32739:6;32695:72;:::i;:::-;32814:9;32808:4;32804:20;32799:2;32788:9;32784:18;32777:48;32842:76;32913:4;32904:6;32842:76;:::i;:::-;32834:84;;32285:640;;;;;;;:::o;32931:141::-;32987:5;33018:6;33012:13;33003:22;;33034:32;33060:5;33034:32;:::i;:::-;32931:141;;;;:::o;33078:349::-;33147:6;33196:2;33184:9;33175:7;33171:23;33167:32;33164:119;;;33202:79;;:::i;:::-;33164:119;33322:1;33347:63;33402:7;33393:6;33382:9;33378:22;33347:63;:::i;:::-;33337:73;;33293:127;33078:349;;;;:::o;33433:180::-;33481:77;33478:1;33471:88;33578:4;33575:1;33568:15;33602:4;33599:1;33592:15;33619:194;33659:4;33679:20;33697:1;33679:20;:::i;:::-;33674:25;;33713:20;33731:1;33713:20;:::i;:::-;33708:25;;33757:1;33754;33750:9;33742:17;;33781:1;33775:4;33772:11;33769:37;;;33786:18;;:::i;:::-;33769:37;33619:194;;;;:::o;33819:180::-;33867:77;33864:1;33857:88;33964:4;33961:1;33954:15;33988:4;33985:1;33978:15
Swarm Source
ipfs://8f99c872c67065b1dd30a7ccd318b5da6093ad2a9223bc08dd09fa5b3549f39f
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.