More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 10 from a total of 10 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Metadata Che... | 59831247 | 270 days ago | IN | 0 POL | 0.00100668 | ||||
Set Metadata Che... | 59829911 | 270 days ago | IN | 0 POL | 0.00100668 | ||||
Set Metadata Che... | 59106841 | 288 days ago | IN | 0 POL | 0.00349662 | ||||
Set Metadata Che... | 59104843 | 289 days ago | IN | 0 POL | 0.0015074 | ||||
Mint Non Fungibl... | 58908917 | 293 days ago | IN | 0 POL | 0.01215851 | ||||
Mint Non Fungibl... | 58830362 | 295 days ago | IN | 0 POL | 0.04196676 | ||||
Mint Non Fungibl... | 58427741 | 305 days ago | IN | 0 POL | 0.181866 | ||||
Mint Non Fungibl... | 58427405 | 305 days ago | IN | 0 POL | 0.00444399 | ||||
Set Minter | 58424004 | 306 days ago | IN | 0 POL | 0.00182495 | ||||
Set Controller | 58423989 | 306 days ago | IN | 0 POL | 0.00316272 |
Loading...
Loading
Contract Name:
ERC1155Token
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2024-06-24 */ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // 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); } } // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { bool private _paused; /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } } // 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; } } // 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); } } } // 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)); } } // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } } pragma solidity ^0.8.20; /** * @title SignatureBouncer * @author PhABC, Shrugs and aflesher * @dev SignatureBouncer allows users to submit a signature as a permission to * do an action. * If the signature is from one of the authorized signer addresses, the * signature is valid. * Note that SignatureBouncer offers no protection against replay attacks, users * must add this themselves! * * Signer addresses can be individual servers signing grants or different * users within a decentralized club that have permission to invite other * members. This technique is useful for whitelists and airdrops; instead of * putting all valid addresses on-chain, simply sign a grant of the form * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a * valid signer address. * Then restrict access to your crowdsale/whitelist/airdrop using the * `onlyValidSignature` modifier (or implement your own using _isValidSignature). * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and * `onlyValidSignatureAndData` can be used to restrict access to only a given * method or a given method with given parameters respectively. * See the tests in SignatureBouncer.test.js for specific usage examples. * * @notice A method that uses the `onlyValidSignatureAndData` modifier must make * the _signature parameter the "last" parameter. You cannot sign a message that * has its own signature in it so the last 128 bytes of msg.data (which * represents the length of the _signature data and the _signature data itself) * is ignored when validating. Also non fixed sized parameters make constructing * the data in the signature much more complex. * See https://ethereum.stackexchange.com/a/50616 for more details. */ contract SignatureBouncer is Context { using ECDSA for bytes32; using MessageHashUtils for bytes32; // Function selectors are 4 bytes long, as documented in // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector uint256 private constant _METHOD_ID_SIZE = 4; // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes uint256 private constant _SIGNATURE_SIZE = 96; // Address with the signer role address public signer; /** * @dev Invalid signature for caller and data. */ error SignatureBouncerInvalidSignature(); /** * @dev Data is too short. */ error SignatureBouncerTooShortData(); /** * @dev Sets the value for {signer}. * This value is immutable: it can only be set once during construction. */ constructor(address _signer) { signer = _signer; } /** * @dev Requires that a valid signature with a specified method and params of a signer was provided. */ modifier onlyValidSignatureAndData(bytes memory signature) { if (!_isValidSignatureAndData(_msgSender(), signature)) { revert SignatureBouncerInvalidSignature(); } _; } /** * @dev is the signature of `this + account + methodId + params(s)` from a signer? * @notice the signature parameter of the method being validated must be the "last" parameter * @return bool */ function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) { bytes memory msgData = _msgData(); if (msgData.length <= _SIGNATURE_SIZE) { revert SignatureBouncerTooShortData(); } bytes memory data = new bytes(msgData.length - _SIGNATURE_SIZE); for (uint256 i = 0; i < data.length; i++) { data[i] = msgData[i]; } return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); } /** * @dev Internal function to convert a hash to an eth signed message * and then recover the signature and check it against the signer role. * @return bool */ function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) { address _signer = hash.toEthSignedMessageHash().recover(signature); return _signer != address(0) && isSigner(_signer); } /** * @dev Public function to check if given address has the signer role. * @return bool */ function isSigner(address account) public view returns (bool) { return signer == account; } } pragma solidity ^0.8.20; /** * @title Controller * @dev Contract used by controllers. */ contract Controller is Ownable, Pausable, SignatureBouncer { mapping(bytes => bool) private signatures; /** * @dev The `signer` is invalid (zero address or a contract). */ error ControllerInvalidSigner(address signer); /** * @dev The `signatureTimestamp` is invalid (outdated or premature compared to `blockTimestamp`). */ error ControllerInvalidTimestamp(uint256 signatureTimestamp, uint256 blockTimestamp); /** * @dev The `signature` is invalid for caller and data. */ error ControllerInvalidSignature(bytes signature); /** * @dev The `signature` was already used. */ error ControllerAlreadyUsedSignature(bytes signature); /** * @dev Requires that a valid `signature` was provided. */ modifier onlyValidSignature(bytes calldata signature) { _isValidSignature(signature); _; } /** * @dev Requires that a valid `signature` and `timestamp` were provided. */ modifier onlyValidSignatureAndTimestamp(bytes calldata signature, uint256 timestamp) { if (timestamp < block.timestamp - 1 hours || timestamp > block.timestamp + 1 hours) { revert ControllerInvalidTimestamp(timestamp, block.timestamp); } _isValidSignature(signature); _; } /** * @dev Sets the `signer` address. */ constructor(address signer) Ownable(_msgSender()) SignatureBouncer(signer) { if (signer == address(0) || signer.code.length > 0) { revert ControllerInvalidSigner(signer); } } /** * @dev Marks `signature` as used. */ function _markSignatureAsUsed(bytes calldata signature) internal { signatures[signature] = true; } /** * @dev Checks if a valid `signature` was provided. */ function _isValidSignature(bytes calldata signature) internal view { _requireNotPaused(); if (wasSignatureUsed(signature)) { revert ControllerAlreadyUsedSignature(signature); } if (!_isValidSignatureAndData(_msgSender(), signature)) { revert ControllerInvalidSignature(signature); } } /** * @dev Marks signatures usage as disabled. */ function pauseSignatures() onlyOwner external { _pause(); } /** * @dev Marks signatures usage as enabled. */ function unpauseSignatures() onlyOwner external { _unpause(); } /** * @dev Returns true it the `signature` was already used. */ function wasSignatureUsed(bytes calldata signature) public view returns (bool) { return signatures[signature]; } } // 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); } // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.20; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) external view returns (address receiver, uint256 royaltyAmount); } // OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the value of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments. * * Requirements: * * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external; } // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); } // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.20; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); } // 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; } } // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } } // OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to array types. */ library Arrays { using StorageSlot for bytes32; /** * @dev Searches a sorted `array` and returns the first index that contains * a value greater or equal to `element`. If no such index exists (i.e. all * values in the array are strictly less than `element`), the array length is * returned. Time complexity O(log n). * * `array` is expected to be sorted in ascending order, and to contain no * repeated elements. */ function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeAccess(array, mid).value > element) { high = mid; } else { low = mid + 1; } } // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. if (low > 0 && unsafeAccess(array, low - 1).value == element) { return low - 1; } else { return low; } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getAddressSlot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getBytes32Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getUint256Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } } // 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); } // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 */ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors { using Arrays for uint256[]; using Arrays for address[]; mapping(uint256 id => mapping(address account => uint256)) private _balances; mapping(address account => mapping(address operator => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256 /* id */) public view virtual returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. */ function balanceOf(address account, uint256 id) public view virtual returns (uint256) { return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] memory accounts, uint256[] memory ids ) public view virtual returns (uint256[] memory) { if (accounts.length != ids.length) { revert ERC1155InvalidArrayLength(ids.length, accounts.length); } uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i)); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeTransferFrom(from, to, id, value, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeBatchTransferFrom(from, to, ids, values, data); } /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` * (or `to`) is the zero address. * * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. * * Requirements: * * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. * - `ids` and `values` must have the same length. * * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. */ function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual { if (ids.length != values.length) { revert ERC1155InvalidArrayLength(ids.length, values.length); } address operator = _msgSender(); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids.unsafeMemoryAccess(i); uint256 value = values.unsafeMemoryAccess(i); if (from != address(0)) { uint256 fromBalance = _balances[id][from]; if (fromBalance < value) { revert ERC1155InsufficientBalance(from, fromBalance, value, id); } unchecked { // Overflow not possible: value <= fromBalance _balances[id][from] = fromBalance - value; } } if (to != address(0)) { _balances[id][to] += value; } } if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); emit TransferSingle(operator, from, to, id, value); } else { emit TransferBatch(operator, from, to, ids, values); } } /** * @dev Version of {_update} that performs the token acceptance check by calling * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it * contains code (eg. is a smart contract at the moment of execution). * * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any * update to the contract state after this function would break the check-effect-interaction pattern. Consider * overriding {_update} instead. */ function _updateWithAcceptanceCheck( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal virtual { _update(from, to, ids, values); if (to != address(0)) { address operator = _msgSender(); if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); _doSafeTransferAcceptanceCheck(operator, from, to, id, value, data); } else { _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data); } } } /** * @dev Transfers a `value` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. * - `ids` and `values` must have the same length. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the values in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `values` must have the same length. * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev Destroys a `value` amount of tokens of type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. */ function _burn(address from, uint256 id, uint256 value) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. * - `ids` and `values` must have the same length. */ function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the zero address. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Performs an acceptance check by calling {IERC1155-onERC1155Received} on the `to` address * if it contains code at the moment of execution. */ function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 value, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Performs a batch acceptance check by calling {IERC1155-onERC1155BatchReceived} on the `to` address * if it contains code at the moment of execution. */ function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Creates an array in memory with only one value for each of the elements provided. */ function _asSingletonArrays( uint256 element1, uint256 element2 ) private pure returns (uint256[] memory array1, uint256[] memory array2) { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer array1 := mload(0x40) // Set array length to 1 mstore(array1, 1) // Store the single element at the next word after the length (where content starts) mstore(add(array1, 0x20), element1) // Repeat for next array locating it right after the first array array2 := add(array1, 0x40) mstore(array2, 1) mstore(add(array2, 0x20), element2) // Update the free memory pointer by pointing after the second array mstore(0x40, add(array2, 0x40)) } } } // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.20; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. * * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens * that can be minted. * * CAUTION: This extension should not be added in an upgrade to an already deployed contract. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 id => uint256) private _totalSupply; uint256 private _totalSupplyAll; /** * @dev Total value of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Total value of tokens. */ function totalSupply() public view virtual returns (uint256) { return _totalSupplyAll; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return totalSupply(id) > 0; } /** * @dev See {ERC1155-_update}. */ function _update( address from, address to, uint256[] memory ids, uint256[] memory values ) internal virtual override { super._update(from, to, ids, values); if (from == address(0)) { uint256 totalMintValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values[i]; // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply[ids[i]] += value; totalMintValue += value; } // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows _totalSupplyAll += totalMintValue; } if (to == address(0)) { uint256 totalBurnValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values[i]; unchecked { // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i]) _totalSupply[ids[i]] -= value; // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll totalBurnValue += value; } } unchecked { // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll _totalSupplyAll -= totalBurnValue; } } } } pragma solidity ^0.8.20; /** * @title Controllable * @dev Contract used for handling controllers. */ contract Controllable is Ownable { address public controller; /** * @dev The `account` is not authorized. */ error ControllableUnauthorizedAccount(address account); /** * @dev The controller address is the same as current one. */ error ControllableTheSameValue(); /** * @dev The `controller` is invalid (zero address or not a contract). */ error ControllableInvalidController(address controller); /** * @dev Emitted when the `controller` is set to a new address. */ event ControllerChanged(address indexed controller); /** * @dev Throws if called by any account other than the controller. */ modifier onlyController() { if (msg.sender != controller) { revert ControllableUnauthorizedAccount(msg.sender); } _; } /** * @dev Throws if called by any account other than the controller or the owner. */ modifier onlyControllerOrOwner() { if (msg.sender != controller && msg.sender != owner()) { revert ControllableUnauthorizedAccount(msg.sender); } _; } /** * @dev Initializes the contract. */ constructor() Ownable(_msgSender()) {} /** * @dev Sets address of the controller to `newController`. */ function setController(address newController) external onlyOwner { if (newController == controller) { revert ControllableTheSameValue(); } if (newController == address(0) || newController.code.length == 0) { revert ControllableInvalidController(newController); } controller = newController; emit ControllerChanged(controller); } } pragma solidity ^0.8.20; /** * @title ERC1155Token * @dev ERC1155 token contract. */ contract ERC1155Token is Controllable, ERC1155Supply, IERC2981 { using Math for uint256; using Strings for uint160; using Strings for uint256; struct Royalty { address beneficiary; uint8 percent; bool isSet; } address public minter; string private _uriPrefix; mapping(uint256 => uint256) private _checksums; mapping(uint256 => Royalty) private _tokenRoyalties; /** * @dev The `account` is not authorized. */ error ERC1155TokenUnauthorizedAccount(address account); /** * @dev Token identified by `identifier` already exists. */ error ERC1155TokenIdentifierAlreadyExists(uint256 identifier); /** * @dev Token identified by `identifier` does not exist. */ error ERC1155TokenIdentifierDoesNotExist(uint256 identifier); /** * @dev Value is the same as current one. */ error ERC1155TokenTheSameValue(); /** * @dev List cannot be empty. */ error ERC1155TokenEmptyList(); /** * @dev Lists must have the same length. */ error ERC1155TokenListsLengthMismatch(); /** * @dev Emitted when the metadata `uriPrefix` is set to a new URI. */ event MetadataUriChanged(string indexed uriPrefix); /** * @dev Emitted when the `checksum` of token identified by `identifier` is set to a new value. */ event MetadataChecksumChanged(uint256 indexed identifier, uint256 indexed checksum); /** * @dev Emitted when the `checksums` of tokens identified by `identifiers` are set to new values. */ event MetadataChecksumBatchChanged(uint256[] indexed identifiers, uint256[] indexed checksums); /** * @dev Emitted when the `minter` address changes. */ event MinterChanged(address indexed minter); /** * @dev Creates token instance with URI prefix set to `uriPrefix`. */ constructor(string memory uriPrefix) ERC1155("") { minter = msg.sender; _uriPrefix = uriPrefix; emit MetadataUriChanged(uriPrefix); emit MinterChanged(minter); } /** * @dev Throws if called by any account other than the controller or the minter. */ modifier onlyControllerOrMinter() { if (msg.sender != controller && msg.sender != minter) { revert ERC1155TokenUnauthorizedAccount(msg.sender); } _; } /** * @dev Throws if called by any account other than the minter. */ modifier onlyMinter() { if (msg.sender != minter) { revert ERC1155TokenUnauthorizedAccount(msg.sender); } _; } /** * @dev Requires that a token with given `identifier` exists. */ modifier onlyExistingToken(uint256 identifier) { if (!exists(identifier)) { revert ERC1155TokenIdentifierDoesNotExist(identifier); } _; } /** * @dev Allows to mint non-fungible token identified by `identifier` and `checksum` by the controller or the owner and assign it to `beneficiary`. */ function mintNonFungible(uint256 identifier, uint256 checksum, address beneficiary) external onlyControllerOrMinter { if (exists(identifier)) { revert ERC1155TokenIdentifierAlreadyExists(identifier); } if (checksum > 0) { _checksums[identifier] = checksum; } _mint(beneficiary, identifier, 1, ""); emit MetadataChecksumChanged(identifier, checksum); } /** * @dev Allows to mint multiple non-fungible tokens identified by `identifiers` and `checksums` by the controller or the owner and assign them to `beneficiary`. */ function mintNonFungibleBatch(uint256[] calldata identifiers, uint256[] calldata checksums, address beneficiary) external onlyControllerOrMinter { uint256[] memory values = new uint256[](identifiers.length); for (uint256 i = 0; i < identifiers.length; ++i) { if (exists(identifiers[i])) { revert ERC1155TokenIdentifierAlreadyExists(identifiers[i]); } values[i] = 1; if (checksums[i] > 0) { _checksums[identifiers[i]] = checksums[i]; } } _mintBatch(beneficiary, identifiers, values, ""); emit MetadataChecksumBatchChanged(identifiers, checksums); } /** * @dev Sets metadata URI prefix to `uriPrefix`. */ function setMetadataUriPrefix(string calldata uriPrefix) external onlyOwner { if (keccak256(abi.encodePacked(_uriPrefix)) == keccak256(abi.encodePacked(uriPrefix))) { revert ERC1155TokenTheSameValue(); } _uriPrefix = uriPrefix; emit MetadataUriChanged(uriPrefix); } /** * @dev Sets metadata checksum for given `identifier` to `checksum`. */ function setMetadataChecksum(uint256 identifier, uint256 checksum) external onlyMinter onlyExistingToken(identifier) { if (_checksums[identifier] == checksum) { revert ERC1155TokenTheSameValue(); } _checksums[identifier] = checksum; emit MetadataChecksumChanged(identifier, checksum); } /** * @dev Sets metadata checksums for given `identifiers` to `checksums`. */ function setMetadataChecksumBatch(uint256[] calldata identifiers, uint256[] calldata checksums) external onlyMinter { if (identifiers.length == 0 || checksums.length == 0) { revert ERC1155TokenEmptyList(); } if (identifiers.length != checksums.length) { revert ERC1155TokenListsLengthMismatch(); } for (uint256 i = 0; i < identifiers.length; ++i) { if (!exists(identifiers[i])) { revert ERC1155TokenIdentifierDoesNotExist(identifiers[i]); } if (_checksums[identifiers[i]] == checksums[i]) { revert ERC1155TokenTheSameValue(); } _checksums[identifiers[i]] = checksums[i]; } emit MetadataChecksumBatchChanged(identifiers, checksums); } /** * @dev Sets royalty info (`beneficiary` and `percent`) for token identified by `identifier`. */ function setTokenRoyaltyInfo(uint256 identifier, address beneficiary, uint8 percent) external onlyControllerOrMinter onlyExistingToken(identifier) { if (beneficiary == address(0)) { delete _tokenRoyalties[identifier]; } else { _tokenRoyalties[identifier] = Royalty(beneficiary, percent, true); } } /** * @dev Sets minter address to `newMinter`. */ function setMinter(address newMinter) external onlyOwner { if (newMinter == minter) { revert ERC1155TokenTheSameValue(); } minter = newMinter; emit MinterChanged(newMinter); } /** * @dev Returns metadata URI for given `identifier`. */ function uri(uint256 identifier) public view override onlyExistingToken(identifier) returns (string memory) { return string(abi.encodePacked(_uriPrefix, uint160(address(this)).toHexString(), "/", identifier.toString(), ".json")); } /** * @dev Returns metadata checksum for given `identifier`. */ function metadataChecksum(uint256 identifier) external view onlyExistingToken(identifier) returns (string memory) { if (_checksums[identifier] == 0) { return ""; } bytes memory hexString = bytes(_checksums[identifier].toHexString()); bytes memory checksumString = new bytes(64); uint256 offset = 66 - hexString.length; for (uint64 i = 0; i < offset; ++i) { checksumString[i] = 0x30; } for (uint64 i = 0; i < hexString.length - 2; ++i) { checksumString[i + offset] = hexString[i + 2]; } return string(checksumString); } /** * @dev Returns beneficiary and percent for given `royalty`. */ function _royalty(Royalty storage royalty) internal view returns (address, uint8) { return (royalty.beneficiary, royalty.percent); } /** * @dev Returns beneficiary and percent for token identified by `identifier` if this token has dedicated settings. */ function tokenRoyalty(uint256 identifier) external view onlyExistingToken(identifier) returns (address, uint8) { return _royalty(_tokenRoyalties[identifier]); } /** * @dev See {IERC2981-royaltyInfo}. */ function royaltyInfo(uint256 identifier, uint256 salePrice) public view override onlyExistingToken(identifier) returns (address, uint256) { Royalty memory royalty = _tokenRoyalties[identifier]; if (!royalty.isSet) { return (address(0), 0); } if (salePrice == 0) { return (royalty.beneficiary, 0); } return (royalty.beneficiary, salePrice.mulDiv(royalty.percent, 100)); } /** * @dev Returns TRUE if token identified by `identifier` has own royalty settings. */ function hasTokenRoyalty(uint256 identifier) external view onlyExistingToken(identifier) returns (bool) { return _tokenRoyalties[identifier].isSet; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceIdentifier) public view override(ERC1155, IERC165) returns (bool) { return interfaceIdentifier == type(IERC2981).interfaceId || super.supportsInterface(interfaceIdentifier); } } pragma solidity ^0.8.20; /** * @title ERC1155TokenController * @dev Controller of ERC1155 token contract. */ contract ERC1155TokenController is Controller { address private _token; /** * @dev The `token` is invalid (zero address or not a contract). */ error ERC1155TokenControllerInvalidToken(address token); /** * @dev List cannot be empty. */ error ERC1155TokenControllerEmptyList(); /** * @dev Lists must have the same length. */ error ERC1155TokenControllerListsLengthMismatch(); /** * @dev Emitted when the token identified by the `identifier` is minted for the `beneficiary`. */ event Mint(uint256 indexed identifier, address indexed beneficiary); /** * @dev Emitted when tokens identified by `identifiers` are minted for the `beneficiary`. */ event MintBatch(uint256[] indexed identifier, address indexed beneficiary); /** * @dev Creates token controller instance with token set to `token` and signer set to `signer`. */ constructor(address token, address signer) Controller(signer) { if (token == address(0) || token.code.length == 0) { revert ERC1155TokenControllerInvalidToken(token); } _token = token; } /** * @dev Allows to mint non-fungible token identified by `identifier` and `checksum` by bearer of valid `signature` and assign it to `beneficiary`. */ function mintNonFungible(uint256 identifier, uint256 checksum, address beneficiary, uint256 timestamp, bytes calldata signature) external onlyValidSignatureAndTimestamp(signature, timestamp) { _markSignatureAsUsed(signature); ERC1155Token(_token).mintNonFungible(identifier, checksum, beneficiary); emit Mint(identifier, beneficiary); } /** * @dev Allows to mint multiple non-fungible tokens identified by `identifiers` by bearer of valid `signature` and assign them to `beneficiary`. */ function mintNonFungibleBatch(uint256[] calldata identifiers, uint256[] calldata checksums, address beneficiary, uint256 timestamp, bytes calldata signature) external onlyValidSignatureAndTimestamp(signature, timestamp) { if (identifiers.length == 0 || checksums.length == 0) { revert ERC1155TokenControllerEmptyList(); } if (identifiers.length != checksums.length) { revert ERC1155TokenControllerListsLengthMismatch(); } _markSignatureAsUsed(signature); ERC1155Token(_token).mintNonFungibleBatch(identifiers, checksums, beneficiary); emit MintBatch(identifiers, beneficiary); } /** * @dev Sets royalty info (`beneficiary` and `percent`) for token identified by `identifier` by bearer of valid `signature`. */ function setTokenRoyaltyInfo(uint256 identifier, address beneficiary, uint8 percent, uint256 timestamp, bytes calldata signature) external onlyValidSignatureAndTimestamp(signature, timestamp) { _markSignatureAsUsed(signature); ERC1155Token(_token).setTokenRoyaltyInfo(identifier, beneficiary, percent); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"uriPrefix","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"ControllableInvalidController","type":"error"},{"inputs":[],"name":"ControllableTheSameValue","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"ControllableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[],"name":"ERC1155TokenEmptyList","type":"error"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"}],"name":"ERC1155TokenIdentifierAlreadyExists","type":"error"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"}],"name":"ERC1155TokenIdentifierDoesNotExist","type":"error"},{"inputs":[],"name":"ERC1155TokenListsLengthMismatch","type":"error"},{"inputs":[],"name":"ERC1155TokenTheSameValue","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"ERC1155TokenUnauthorizedAccount","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"StringsInsufficientHexLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"}],"name":"ControllerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256[]","name":"identifiers","type":"uint256[]"},{"indexed":true,"internalType":"uint256[]","name":"checksums","type":"uint256[]"}],"name":"MetadataChecksumBatchChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"identifier","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"checksum","type":"uint256"}],"name":"MetadataChecksumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"uriPrefix","type":"string"}],"name":"MetadataUriChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"}],"name":"MinterChanged","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":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"}],"name":"hasTokenRoyalty","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"}],"name":"metadataChecksum","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"checksum","type":"uint256"},{"internalType":"address","name":"beneficiary","type":"address"}],"name":"mintNonFungible","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"identifiers","type":"uint256[]"},{"internalType":"uint256[]","name":"checksums","type":"uint256[]"},{"internalType":"address","name":"beneficiary","type":"address"}],"name":"mintNonFungibleBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","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":"address","name":"newController","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"checksum","type":"uint256"}],"name":"setMetadataChecksum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"identifiers","type":"uint256[]"},{"internalType":"uint256[]","name":"checksums","type":"uint256[]"}],"name":"setMetadataChecksumBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uriPrefix","type":"string"}],"name":"setMetadataUriPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMinter","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint8","name":"percent","type":"uint8"}],"name":"setTokenRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceIdentifier","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"}],"name":"tokenRoyalty","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"identifier","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801562000010575f80fd5b50604051620054a9380380620054a983398181016040528101906200003691906200044f565b60405180602001604052805f81525062000055620001ed60201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000c8575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000bf9190620004e1565b60405180910390fd5b620000d981620001f460201b60201c565b50620000eb81620002b560201b60201c565b503360075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890816200013d919062000733565b50806040516200014e919062000857565b60405180910390207fbf212f907e9933754ffa70bbc0251a1fe289759b6660bff05ba9c028bfda364b60405160405180910390a260075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb6b8f1859c5c352e5ffad07d0f77e384ac725512c015bd3a3ffc885831c8a42560405160405180910390a2506200086f565b5f33905090565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8060049081620002c6919062000733565b5050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200032b82620002e3565b810181811067ffffffffffffffff821117156200034d576200034c620002f3565b5b80604052505050565b5f62000361620002ca565b90506200036f828262000320565b919050565b5f67ffffffffffffffff821115620003915762000390620002f3565b5b6200039c82620002e3565b9050602081019050919050565b5f5b83811015620003c8578082015181840152602081019050620003ab565b5f8484015250505050565b5f620003e9620003e38462000374565b62000356565b905082815260208101848484011115620004085762000407620002df565b5b62000415848285620003a9565b509392505050565b5f82601f830112620004345762000433620002db565b5b815162000446848260208601620003d3565b91505092915050565b5f60208284031215620004675762000466620002d3565b5b5f82015167ffffffffffffffff811115620004875762000486620002d7565b5b62000495848285016200041d565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620004c9826200049e565b9050919050565b620004db81620004bd565b82525050565b5f602082019050620004f65f830184620004d0565b92915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200054b57607f821691505b60208210810362000561576200056062000506565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620005c57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000588565b620005d1868362000588565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200061b620006156200060f84620005e9565b620005f2565b620005e9565b9050919050565b5f819050919050565b6200063683620005fb565b6200064e620006458262000622565b84845462000594565b825550505050565b5f90565b6200066462000656565b620006718184846200062b565b505050565b5b8181101562000698576200068c5f826200065a565b60018101905062000677565b5050565b601f821115620006e757620006b18162000567565b620006bc8462000579565b81016020851015620006cc578190505b620006e4620006db8562000579565b83018262000676565b50505b505050565b5f82821c905092915050565b5f620007095f1984600802620006ec565b1980831691505092915050565b5f620007238383620006f8565b9150826002028217905092915050565b6200073e82620004fc565b67ffffffffffffffff8111156200075a5762000759620002f3565b5b62000766825462000533565b620007738282856200069c565b5f60209050601f831160018114620007a9575f841562000794578287015190505b620007a0858262000716565b8655506200080f565b601f198416620007b98662000567565b5f5b82811015620007e257848901518255600182019150602085019450602081019050620007bb565b86831015620008025784890151620007fe601f891682620006f8565b8355505b6001600288020188555050505b505050505050565b5f81905092915050565b5f6200082d82620004fc565b62000839818562000817565b93506200084b818560208601620003a9565b80840191505092915050565b5f62000864828462000821565b915081905092915050565b614c2c806200087d5f395ff3fe608060405234801561000f575f80fd5b50600436106101c1575f3560e01c8063715018a6116100f7578063c0de11ef11610095578063f242432a1161006f578063f242432a14610537578063f2fde38b14610553578063f77c47911461056f578063fca3b5aa1461058d576101c1565b8063c0de11ef146104cf578063d0f21623146104eb578063e985e9c514610507576101c1565b8063a22cb465116100d1578063a22cb4651461044b578063ad2628cd14610467578063b88cbbd214610483578063bd85b0391461049f576101c1565b8063715018a6146104075780638da5cb5b1461041157806392eefe9b1461042f576101c1565b80632a55205a116101645780634e1273f41161013e5780634e1273f41461036f5780634f558e791461039f57806355f022ba146103cf5780636f5b6563146103eb576101c1565b80632a55205a146102f25780632eb2c2d6146103235780633b13be251461033f576101c1565b80630e89341c116101a05780630e89341c1461024357806318160ddd146102735780631ff4a4201461029157806325762271146102c2576101c1565b8062fdd58e146101c557806301ffc9a7146101f55780630754617214610225575b5f80fd5b6101df60048036038101906101da91906136cc565b6105a9565b6040516101ec9190613719565b60405180910390f35b61020f600480360381019061020a9190613787565b6105ff565b60405161021c91906137cc565b60405180910390f35b61022d610678565b60405161023a91906137f4565b60405180910390f35b61025d6004803603810190610258919061380d565b61069d565b60405161026a91906138c2565b60405180910390f35b61027b61073d565b6040516102889190613719565b60405180910390f35b6102ab60048036038101906102a6919061380d565b610746565b6040516102b99291906138fd565b60405180910390f35b6102dc60048036038101906102d7919061380d565b6107b6565b6040516102e991906138c2565b60405180910390f35b61030c60048036038101906103079190613924565b6109f0565b60405161031a929190613962565b60405180910390f35b61033d60048036038101906103389190613b79565b610b40565b005b6103596004803603810190610354919061380d565b610be7565b60405161036691906137cc565b60405180910390f35b61038960048036038101906103849190613d04565b610c5c565b6040516103969190613e31565b60405180910390f35b6103b960048036038101906103b4919061380d565b610d69565b6040516103c691906137cc565b60405180910390f35b6103e960048036038101906103e49190613924565b610d7c565b005b61040560048036038101906104009190613eaa565b610eeb565b005b61040f61120b565b005b61041961121e565b60405161042691906137f4565b60405180910390f35b61044960048036038101906104449190613f3b565b611245565b005b61046560048036038101906104609190613f90565b61140c565b005b610481600480360381019061047c9190614023565b611422565b005b61049d6004803603810190610498919061406e565b61150c565b005b6104b960048036038101906104b4919061380d565b6116b0565b6040516104c69190613719565b60405180910390f35b6104e960048036038101906104e491906140be565b6116ca565b005b61050560048036038101906105009190614166565b6119a5565b005b610521600480360381019061051c91906141b6565b611c48565b60405161052e91906137cc565b60405180910390f35b610551600480360381019061054c91906141f4565b611cd6565b005b61056d60048036038101906105689190613f3b565b611d7d565b005b610577611e01565b60405161058491906137f4565b60405180910390f35b6105a760048036038101906105a29190613f3b565b611e26565b005b5f60025f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610671575061067082611f3a565b5b9050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060816106a981610d69565b6106ea57806040517fbde6baa50000000000000000000000000000000000000000000000000000000081526004016106e19190613719565b60405180910390fd5b600861070b3073ffffffffffffffffffffffffffffffffffffffff1661201b565b61071485612039565b60405160200161072693929190614444565b604051602081830303815290604052915050919050565b5f600654905090565b5f808261075281610d69565b61079357806040517fbde6baa500000000000000000000000000000000000000000000000000000000815260040161078a9190613719565b60405180910390fd5b6107ac600a5f8681526020019081526020015f20612103565b9250925050915091565b6060816107c281610d69565b61080357806040517fbde6baa50000000000000000000000000000000000000000000000000000000081526004016107fa9190613719565b60405180910390fd5b5f60095f8581526020019081526020015f2054036108315760405180602001604052805f81525091506109ea565b5f61084c60095f8681526020019081526020015f205461201b565b90505f604067ffffffffffffffff81111561086a5761086961398d565b5b6040519080825280601f01601f19166020018201604052801561089c5781602001600182028036833780820191505090505b5090505f825160426108ae91906144b7565b90505f5b818167ffffffffffffffff16101561092557603060f81b838267ffffffffffffffff16815181106108e6576108e56144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053508061091e9061452a565b90506108b2565b505f5b6002845161093691906144b7565b8167ffffffffffffffff1610156109e257836002826109559190614559565b67ffffffffffffffff16815181106109705761096f6144ea565b5b602001015160f81c60f81b83838367ffffffffffffffff166109929190614594565b815181106109a3576109a26144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350806109db9061452a565b9050610928565b508194505050505b50919050565b5f80836109fc81610d69565b610a3d57806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401610a349190613719565b60405180910390fd5b5f600a5f8781526020019081526020015f206040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f820160149054906101000a900460ff1660ff1660ff1681526020015f820160159054906101000a900460ff16151515158152505090508060400151610afb575f809350935050610b38565b5f8503610b1157805f01515f9350935050610b38565b805f0151610b32826020015160ff166064886121429092919063ffffffff16565b93509350505b509250929050565b5f610b49612241565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610b8e5750610b8c8682611c48565b155b15610bd25780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610bc99291906145c7565b60405180910390fd5b610bdf8686868686612248565b505050505050565b5f81610bf281610d69565b610c3357806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401610c2a9190613719565b60405180910390fd5b600a5f8481526020019081526020015f205f0160159054906101000a900460ff16915050919050565b60608151835114610ca857815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610c9f9291906145ee565b60405180910390fd5b5f835167ffffffffffffffff811115610cc457610cc361398d565b5b604051908082528060200260200182016040528015610cf25781602001602082028036833780820191505090505b5090505f5b8451811015610d5e57610d2e610d16828761233c90919063ffffffff16565b610d29838761234f90919063ffffffff16565b6105a9565b828281518110610d4157610d406144ea565b5b60200260200101818152505080610d5790614615565b9050610cf7565b508091505092915050565b5f80610d74836116b0565b119050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e0d57336040517fe5494cc6000000000000000000000000000000000000000000000000000000008152600401610e0491906137f4565b60405180910390fd5b81610e1781610d69565b610e5857806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401610e4f9190613719565b60405180910390fd5b8160095f8581526020019081526020015f205403610ea2576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160095f8581526020019081526020015f208190555081837fc8c7d9aba5aa51ebb81117cf28f9f60ef2bb2b8219fd2dd5dbe3dc7ba9e8a72b60405160405180910390a3505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610f95575060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610fd757336040517fe5494cc6000000000000000000000000000000000000000000000000000000008152600401610fce91906137f4565b60405180910390fd5b5f8585905067ffffffffffffffff811115610ff557610ff461398d565b5b6040519080825280602002602001820160405280156110235781602001602082028036833780820191505090505b5090505f5b8686905081101561114c57611055878783818110611049576110486144ea565b5b90506020020135610d69565b156110b05786868281811061106d5761106c6144ea565b5b905060200201356040517fb1c147ad0000000000000000000000000000000000000000000000000000000081526004016110a79190613719565b60405180910390fd5b60018282815181106110c5576110c46144ea565b5b6020026020010181815250505f8585838181106110e5576110e46144ea565b5b90506020020135111561113b57848482818110611105576111046144ea565b5b9050602002013560095f898985818110611122576111216144ea565b5b9050602002013581526020019081526020015f20819055505b8061114590614615565b9050611028565b506111a7828787808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f820116905080830192505050505050508360405180602001604052805f815250612362565b83836040516111b79291906146ce565b604051809103902086866040516111cf9291906146ce565b60405180910390207f3ea440575b174f0bcd120faa37fac3a98210e03f68a8e3906a6b01d3abc5107760405160405180910390a3505050505050565b6112136123e5565b61121c5f61246c565b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61124d6123e5565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112d3576040517f2264e4cf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132357505f8173ffffffffffffffffffffffffffffffffffffffff163b145b1561136557806040517f288f822800000000000000000000000000000000000000000000000000000000815260040161135c91906137f4565b60405180910390fd5b8060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f027c3e080ed9215f564a9455a666f7e459b3edc0bb6e02a1bf842fde4d0ccfc160405160405180910390a250565b61141e611417612241565b838361252d565b5050565b61142a6123e5565b818160405160200161143d92919061470a565b6040516020818303038152906040528051906020012060086040516020016114659190614722565b60405160208183030381529060405280519060200120036114b2576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181600891826114c39291906148cd565b5081816040516114d492919061470a565b60405180910390207fbf212f907e9933754ffa70bbc0251a1fe289759b6660bff05ba9c028bfda364b60405160405180910390a25050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156115b6575060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156115f857336040517fe5494cc60000000000000000000000000000000000000000000000000000000081526004016115ef91906137f4565b60405180910390fd5b61160183610d69565b1561164357826040517fb1c147ad00000000000000000000000000000000000000000000000000000000815260040161163a9190613719565b60405180910390fd5b5f821115611662578160095f8581526020019081526020015f20819055505b61167d8184600160405180602001604052805f815250612696565b81837fc8c7d9aba5aa51ebb81117cf28f9f60ef2bb2b8219fd2dd5dbe3dc7ba9e8a72b60405160405180910390a3505050565b5f60055f8381526020019081526020015f20549050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461175b57336040517fe5494cc600000000000000000000000000000000000000000000000000000000815260040161175291906137f4565b60405180910390fd5b5f84849050148061176e57505f82829050145b156117a5576040517f8691e5c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181905084849050146117e4576040517f483b9c9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8484905081101561194257611813858583818110611807576118066144ea565b5b90506020020135610d69565b61186d5784848281811061182a576118296144ea565b5b905060200201356040517fbde6baa50000000000000000000000000000000000000000000000000000000081526004016118649190613719565b60405180910390fd5b8282828181106118805761187f6144ea565b5b9050602002013560095f87878581811061189d5761189c6144ea565b5b9050602002013581526020019081526020015f2054036118e9576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8282828181106118fc576118fb6144ea565b5b9050602002013560095f878785818110611919576119186144ea565b5b9050602002013581526020019081526020015f20819055508061193b90614615565b90506117e6565b5081816040516119539291906146ce565b6040518091039020848460405161196b9291906146ce565b60405180910390207f3ea440575b174f0bcd120faa37fac3a98210e03f68a8e3906a6b01d3abc5107760405160405180910390a350505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015611a4f575060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15611a9157336040517fe5494cc6000000000000000000000000000000000000000000000000000000008152600401611a8891906137f4565b60405180910390fd5b82611a9b81610d69565b611adc57806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401611ad39190613719565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611b7357600a5f8581526020019081526020015f205f8082015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555f820160146101000a81549060ff02191690555f820160156101000a81549060ff02191690555050611c42565b60405180606001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018360ff16815260200160011515815250600a5f8681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a81548160ff021916908360ff1602179055506040820151815f0160156101000a81548160ff0219169083151502179055509050505b50505050565b5f60035f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f611cdf612241565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015611d245750611d228682611c48565b155b15611d685780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611d5f9291906145c7565b60405180910390fd5b611d75868686868661272b565b505050505050565b611d856123e5565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611df5575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611dec91906137f4565b60405180910390fd5b611dfe8161246c565b50565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611e2e6123e5565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611eb4576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fb6b8f1859c5c352e5ffad07d0f77e384ac725512c015bd3a3ffc885831c8a42560405160405180910390a250565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061200457507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612014575061201382612831565b5b9050919050565b606061203282600161202c8561289a565b01612923565b9050919050565b60605f600161204784612b61565b0190505f8167ffffffffffffffff8111156120655761206461398d565b5b6040519080825280601f01601f1916602001820160405280156120975781602001600182028036833780820191505090505b5090505f82602001820190505b6001156120f8578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816120ed576120ec61499a565b5b0494505f85036120a4575b819350505050919050565b5f80825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16835f0160149054906101000a900460ff1691509150915091565b5f8083850290505f8019858709828110838203039150505f810361217a578382816121705761216f61499a565b5b049250505061223a565b8084116121b3576040517f227bc15300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8486880990508281118203915080830392505f855f038616905080860495508084049350600181825f0304019050808302841793505f600287600302189050808702600203810290508087026002038102905080870260020381029050808702600203810290508087026002038102905080870260020381029050808502955050505050505b9392505050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122b8575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016122af91906137f4565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612328575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161231f91906137f4565b60405180910390fd5b6123358585858585612cb2565b5050505050565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036123d2575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016123c991906137f4565b60405180910390fd5b6123df5f85858585612cb2565b50505050565b6123ed612241565b73ffffffffffffffffffffffffffffffffffffffff1661240b61121e565b73ffffffffffffffffffffffffffffffffffffffff161461246a5761242e612241565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161246191906137f4565b60405180910390fd5b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361259d575f6040517fced3e10000000000000000000000000000000000000000000000000000000000815260040161259491906137f4565b60405180910390fd5b8060035f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161268991906137cc565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612706575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016126fd91906137f4565b60405180910390fd5b5f806127128585612d5e565b915091506127235f87848487612cb2565b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361279b575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161279291906137f4565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361280b575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161280291906137f4565b60405180910390fd5b5f806128178585612d5e565b915091506128288787848487612cb2565b50505050505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f805f90505f608084901c11156128b957608083901c92506010810190505b5f604084901c11156128d357604083901c92506008810190505b5f602084901c11156128ed57602083901c92506004810190505b5f601084901c111561290757601083901c92506002810190505b5f600884901c111561291a576001810190505b80915050919050565b60605f8390505f600284600261293991906149c7565b6129439190614594565b67ffffffffffffffff81111561295c5761295b61398d565b5b6040519080825280601f01601f19166020018201604052801561298e5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106129c5576129c46144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612a2857612a276144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f6001856002612a6691906149c7565b612a709190614594565b90505b6001811115612b0f577f3031323334353637383961626364656600000000000000000000000000000000600f841660108110612ab257612ab16144ea565b5b1a60f81b828281518110612ac957612ac86144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c925080612b0890614a08565b9050612a73565b505f8214612b565784846040517fe22e27eb000000000000000000000000000000000000000000000000000000008152600401612b4d9291906145ee565b60405180910390fd5b809250505092915050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612bbd577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612bb357612bb261499a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612bfa576d04ee2d6d415b85acef81000000008381612bf057612bef61499a565b5b0492506020810190505b662386f26fc100008310612c2957662386f26fc100008381612c1f57612c1e61499a565b5b0492506010810190505b6305f5e1008310612c52576305f5e1008381612c4857612c4761499a565b5b0492506008810190505b6127108310612c77576127108381612c6d57612c6c61499a565b5b0492506004810190505b60648310612c9a5760648381612c9057612c8f61499a565b5b0492506002810190505b600a8310612ca9576001810190505b80915050919050565b612cbe85858585612d8e565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612d57575f612cfa612241565b90506001845103612d46575f612d195f8661234f90919063ffffffff16565b90505f612d2f5f8661234f90919063ffffffff16565b9050612d3f838989858589612f37565b5050612d55565b612d548187878787876130e6565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b612d9a84848484613295565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612e73575f805b8351811015612e58575f838281518110612ded57612dec6144ea565b5b602002602001015190508060055f878581518110612e0e57612e0d6144ea565b5b602002602001015181526020019081526020015f205f828254612e319190614594565b925050819055508083612e449190614594565b92505080612e5190614615565b9050612dd0565b508060065f828254612e6a9190614594565b92505081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612f31575f805b8351811015612f1f575f838281518110612ec657612ec56144ea565b5b602002602001015190508060055f878581518110612ee757612ee66144ea565b5b602002602001015181526020019081526020015f205f828254039250508190555080830192505080612f1890614615565b9050612ea9565b508060065f8282540392505081905550505b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b11156130de578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401612f97959493929190614a81565b6020604051808303815f875af1925050508015612fd257506040513d601f19601f82011682018060405250810190612fcf9190614aed565b60015b613053573d805f8114613000576040519150601f19603f3d011682016040523d82523d5f602084013e613005565b606091505b505f81510361304b57846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161304291906137f4565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146130dc57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016130d391906137f4565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561328d578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401613146959493929190614b18565b6020604051808303815f875af192505050801561318157506040513d601f19601f8201168201806040525081019061317e9190614aed565b60015b613202573d805f81146131af576040519150601f19603f3d011682016040523d82523d5f602084013e6131b4565b606091505b505f8151036131fa57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016131f191906137f4565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461328b57846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161328291906137f4565b60405180910390fd5b505b505050505050565b80518251146132df57815181516040517f5b0599910000000000000000000000000000000000000000000000000000000081526004016132d69291906145ee565b60405180910390fd5b5f6132e8612241565b90505f5b83518110156134ed575f613309828661234f90919063ffffffff16565b90505f61331f838661234f90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614613444575f60025f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156133ef57888183856040517f03dee4c50000000000000000000000000000000000000000000000000000000081526004016133e69493929190614b7e565b60405180910390fd5b81810360025f8581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16146134da578060025f8481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546134d29190614594565b925050819055505b5050806134e690614615565b90506132ec565b5060018351036135a8575f61350b5f8561234f90919063ffffffff16565b90505f6135215f8561234f90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516135999291906145ee565b60405180910390a45050613627565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161361e929190614bc1565b60405180910390a45b5050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6136688261363f565b9050919050565b6136788161365e565b8114613682575f80fd5b50565b5f813590506136938161366f565b92915050565b5f819050919050565b6136ab81613699565b81146136b5575f80fd5b50565b5f813590506136c6816136a2565b92915050565b5f80604083850312156136e2576136e1613637565b5b5f6136ef85828601613685565b9250506020613700858286016136b8565b9150509250929050565b61371381613699565b82525050565b5f60208201905061372c5f83018461370a565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61376681613732565b8114613770575f80fd5b50565b5f813590506137818161375d565b92915050565b5f6020828403121561379c5761379b613637565b5b5f6137a984828501613773565b91505092915050565b5f8115159050919050565b6137c6816137b2565b82525050565b5f6020820190506137df5f8301846137bd565b92915050565b6137ee8161365e565b82525050565b5f6020820190506138075f8301846137e5565b92915050565b5f6020828403121561382257613821613637565b5b5f61382f848285016136b8565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561386f578082015181840152602081019050613854565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61389482613838565b61389e8185613842565b93506138ae818560208601613852565b6138b78161387a565b840191505092915050565b5f6020820190508181035f8301526138da818461388a565b905092915050565b5f60ff82169050919050565b6138f7816138e2565b82525050565b5f6040820190506139105f8301856137e5565b61391d60208301846138ee565b9392505050565b5f806040838503121561393a57613939613637565b5b5f613947858286016136b8565b9250506020613958858286016136b8565b9150509250929050565b5f6040820190506139755f8301856137e5565b613982602083018461370a565b9392505050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6139c38261387a565b810181811067ffffffffffffffff821117156139e2576139e161398d565b5b80604052505050565b5f6139f461362e565b9050613a0082826139ba565b919050565b5f67ffffffffffffffff821115613a1f57613a1e61398d565b5b602082029050602081019050919050565b5f80fd5b5f613a46613a4184613a05565b6139eb565b90508083825260208201905060208402830185811115613a6957613a68613a30565b5b835b81811015613a925780613a7e88826136b8565b845260208401935050602081019050613a6b565b5050509392505050565b5f82601f830112613ab057613aaf613989565b5b8135613ac0848260208601613a34565b91505092915050565b5f80fd5b5f67ffffffffffffffff821115613ae757613ae661398d565b5b613af08261387a565b9050602081019050919050565b828183375f83830152505050565b5f613b1d613b1884613acd565b6139eb565b905082815260208101848484011115613b3957613b38613ac9565b5b613b44848285613afd565b509392505050565b5f82601f830112613b6057613b5f613989565b5b8135613b70848260208601613b0b565b91505092915050565b5f805f805f60a08688031215613b9257613b91613637565b5b5f613b9f88828901613685565b9550506020613bb088828901613685565b945050604086013567ffffffffffffffff811115613bd157613bd061363b565b5b613bdd88828901613a9c565b935050606086013567ffffffffffffffff811115613bfe57613bfd61363b565b5b613c0a88828901613a9c565b925050608086013567ffffffffffffffff811115613c2b57613c2a61363b565b5b613c3788828901613b4c565b9150509295509295909350565b5f67ffffffffffffffff821115613c5e57613c5d61398d565b5b602082029050602081019050919050565b5f613c81613c7c84613c44565b6139eb565b90508083825260208201905060208402830185811115613ca457613ca3613a30565b5b835b81811015613ccd5780613cb98882613685565b845260208401935050602081019050613ca6565b5050509392505050565b5f82601f830112613ceb57613cea613989565b5b8135613cfb848260208601613c6f565b91505092915050565b5f8060408385031215613d1a57613d19613637565b5b5f83013567ffffffffffffffff811115613d3757613d3661363b565b5b613d4385828601613cd7565b925050602083013567ffffffffffffffff811115613d6457613d6361363b565b5b613d7085828601613a9c565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613dac81613699565b82525050565b5f613dbd8383613da3565b60208301905092915050565b5f602082019050919050565b5f613ddf82613d7a565b613de98185613d84565b9350613df483613d94565b805f5b83811015613e24578151613e0b8882613db2565b9750613e1683613dc9565b925050600181019050613df7565b5085935050505092915050565b5f6020820190508181035f830152613e498184613dd5565b905092915050565b5f80fd5b5f8083601f840112613e6a57613e69613989565b5b8235905067ffffffffffffffff811115613e8757613e86613e51565b5b602083019150836020820283011115613ea357613ea2613a30565b5b9250929050565b5f805f805f60608688031215613ec357613ec2613637565b5b5f86013567ffffffffffffffff811115613ee057613edf61363b565b5b613eec88828901613e55565b9550955050602086013567ffffffffffffffff811115613f0f57613f0e61363b565b5b613f1b88828901613e55565b93509350506040613f2e88828901613685565b9150509295509295909350565b5f60208284031215613f5057613f4f613637565b5b5f613f5d84828501613685565b91505092915050565b613f6f816137b2565b8114613f79575f80fd5b50565b5f81359050613f8a81613f66565b92915050565b5f8060408385031215613fa657613fa5613637565b5b5f613fb385828601613685565b9250506020613fc485828601613f7c565b9150509250929050565b5f8083601f840112613fe357613fe2613989565b5b8235905067ffffffffffffffff81111561400057613fff613e51565b5b60208301915083600182028301111561401c5761401b613a30565b5b9250929050565b5f806020838503121561403957614038613637565b5b5f83013567ffffffffffffffff8111156140565761405561363b565b5b61406285828601613fce565b92509250509250929050565b5f805f6060848603121561408557614084613637565b5b5f614092868287016136b8565b93505060206140a3868287016136b8565b92505060406140b486828701613685565b9150509250925092565b5f805f80604085870312156140d6576140d5613637565b5b5f85013567ffffffffffffffff8111156140f3576140f261363b565b5b6140ff87828801613e55565b9450945050602085013567ffffffffffffffff8111156141225761412161363b565b5b61412e87828801613e55565b925092505092959194509250565b614145816138e2565b811461414f575f80fd5b50565b5f813590506141608161413c565b92915050565b5f805f6060848603121561417d5761417c613637565b5b5f61418a868287016136b8565b935050602061419b86828701613685565b92505060406141ac86828701614152565b9150509250925092565b5f80604083850312156141cc576141cb613637565b5b5f6141d985828601613685565b92505060206141ea85828601613685565b9150509250929050565b5f805f805f60a0868803121561420d5761420c613637565b5b5f61421a88828901613685565b955050602061422b88828901613685565b945050604061423c888289016136b8565b935050606061424d888289016136b8565b925050608086013567ffffffffffffffff81111561426e5761426d61363b565b5b61427a88828901613b4c565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806142cb57607f821691505b6020821081036142de576142dd614287565b5b50919050565b5f81905092915050565b5f819050815f5260205f209050919050565b5f815461430c816142b4565b61431681866142e4565b9450600182165f8114614330576001811461434557614377565b60ff1983168652811515820286019350614377565b61434e856142ee565b5f5b8381101561436f57815481890152600182019150602081019050614350565b838801955050505b50505092915050565b5f61438a82613838565b61439481856142e4565b93506143a4818560208601613852565b80840191505092915050565b7f2f000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6143e46001836142e4565b91506143ef826143b0565b600182019050919050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61442e6005836142e4565b9150614439826143fa565b600582019050919050565b5f61444f8286614300565b915061445b8285614380565b9150614466826143d8565b91506144728284614380565b915061447d82614422565b9150819050949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6144c182613699565b91506144cc83613699565b92508282039050818111156144e4576144e361448a565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f67ffffffffffffffff82169050919050565b5f61453482614517565b915067ffffffffffffffff820361454e5761454d61448a565b5b600182019050919050565b5f61456382614517565b915061456e83614517565b9250828201905067ffffffffffffffff81111561458e5761458d61448a565b5b92915050565b5f61459e82613699565b91506145a983613699565b92508282019050808211156145c1576145c061448a565b5b92915050565b5f6040820190506145da5f8301856137e5565b6145e760208301846137e5565b9392505050565b5f6040820190506146015f83018561370a565b61460e602083018461370a565b9392505050565b5f61461f82613699565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146515761465061448a565b5b600182019050919050565b5f81905092915050565b5f80fd5b82818337505050565b5f61467e838561465c565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156146b1576146b0614666565b5b6020830292506146c283858461466a565b82840190509392505050565b5f6146da828486614673565b91508190509392505050565b5f6146f183856142e4565b93506146fe838584613afd565b82840190509392505050565b5f6147168284866146e6565b91508190509392505050565b5f61472d8284614300565b915081905092915050565b5f82905092915050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261478c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614751565b6147968683614751565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6147d16147cc6147c784613699565b6147ae565b613699565b9050919050565b5f819050919050565b6147ea836147b7565b6147fe6147f6826147d8565b84845461475d565b825550505050565b5f90565b614812614806565b61481d8184846147e1565b505050565b5b81811015614840576148355f8261480a565b600181019050614823565b5050565b601f82111561488557614856816142ee565b61485f84614742565b8101602085101561486e578190505b61488261487a85614742565b830182614822565b50505b505050565b5f82821c905092915050565b5f6148a55f198460080261488a565b1980831691505092915050565b5f6148bd8383614896565b9150826002028217905092915050565b6148d78383614738565b67ffffffffffffffff8111156148f0576148ef61398d565b5b6148fa82546142b4565b614905828285614844565b5f601f831160018114614932575f8415614920578287013590505b61492a85826148b2565b865550614991565b601f198416614940866142ee565b5f5b8281101561496757848901358255600182019150602085019450602081019050614942565b868310156149845784890135614980601f891682614896565b8355505b6001600288020188555050505b50505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6149d182613699565b91506149dc83613699565b92508282026149ea81613699565b91508282048414831517614a0157614a0061448a565b5b5092915050565b5f614a1282613699565b91505f8203614a2457614a2361448a565b5b600182039050919050565b5f81519050919050565b5f82825260208201905092915050565b5f614a5382614a2f565b614a5d8185614a39565b9350614a6d818560208601613852565b614a768161387a565b840191505092915050565b5f60a082019050614a945f8301886137e5565b614aa160208301876137e5565b614aae604083018661370a565b614abb606083018561370a565b8181036080830152614acd8184614a49565b90509695505050505050565b5f81519050614ae78161375d565b92915050565b5f60208284031215614b0257614b01613637565b5b5f614b0f84828501614ad9565b91505092915050565b5f60a082019050614b2b5f8301886137e5565b614b3860208301876137e5565b8181036040830152614b4a8186613dd5565b90508181036060830152614b5e8185613dd5565b90508181036080830152614b728184614a49565b90509695505050505050565b5f608082019050614b915f8301876137e5565b614b9e602083018661370a565b614bab604083018561370a565b614bb8606083018461370a565b95945050505050565b5f6040820190508181035f830152614bd98185613dd5565b90508181036020830152614bed8184613dd5565b9050939250505056fea26469706673582212204663c8f2a003d356b3ae3c524b082d5ed7e152a008b25704ce6ceb0b7942b61464736f6c634300081400330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6e66742e736d617274766572756d2e636f6d2f76612f706f6c79676f6e2f0000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101c1575f3560e01c8063715018a6116100f7578063c0de11ef11610095578063f242432a1161006f578063f242432a14610537578063f2fde38b14610553578063f77c47911461056f578063fca3b5aa1461058d576101c1565b8063c0de11ef146104cf578063d0f21623146104eb578063e985e9c514610507576101c1565b8063a22cb465116100d1578063a22cb4651461044b578063ad2628cd14610467578063b88cbbd214610483578063bd85b0391461049f576101c1565b8063715018a6146104075780638da5cb5b1461041157806392eefe9b1461042f576101c1565b80632a55205a116101645780634e1273f41161013e5780634e1273f41461036f5780634f558e791461039f57806355f022ba146103cf5780636f5b6563146103eb576101c1565b80632a55205a146102f25780632eb2c2d6146103235780633b13be251461033f576101c1565b80630e89341c116101a05780630e89341c1461024357806318160ddd146102735780631ff4a4201461029157806325762271146102c2576101c1565b8062fdd58e146101c557806301ffc9a7146101f55780630754617214610225575b5f80fd5b6101df60048036038101906101da91906136cc565b6105a9565b6040516101ec9190613719565b60405180910390f35b61020f600480360381019061020a9190613787565b6105ff565b60405161021c91906137cc565b60405180910390f35b61022d610678565b60405161023a91906137f4565b60405180910390f35b61025d6004803603810190610258919061380d565b61069d565b60405161026a91906138c2565b60405180910390f35b61027b61073d565b6040516102889190613719565b60405180910390f35b6102ab60048036038101906102a6919061380d565b610746565b6040516102b99291906138fd565b60405180910390f35b6102dc60048036038101906102d7919061380d565b6107b6565b6040516102e991906138c2565b60405180910390f35b61030c60048036038101906103079190613924565b6109f0565b60405161031a929190613962565b60405180910390f35b61033d60048036038101906103389190613b79565b610b40565b005b6103596004803603810190610354919061380d565b610be7565b60405161036691906137cc565b60405180910390f35b61038960048036038101906103849190613d04565b610c5c565b6040516103969190613e31565b60405180910390f35b6103b960048036038101906103b4919061380d565b610d69565b6040516103c691906137cc565b60405180910390f35b6103e960048036038101906103e49190613924565b610d7c565b005b61040560048036038101906104009190613eaa565b610eeb565b005b61040f61120b565b005b61041961121e565b60405161042691906137f4565b60405180910390f35b61044960048036038101906104449190613f3b565b611245565b005b61046560048036038101906104609190613f90565b61140c565b005b610481600480360381019061047c9190614023565b611422565b005b61049d6004803603810190610498919061406e565b61150c565b005b6104b960048036038101906104b4919061380d565b6116b0565b6040516104c69190613719565b60405180910390f35b6104e960048036038101906104e491906140be565b6116ca565b005b61050560048036038101906105009190614166565b6119a5565b005b610521600480360381019061051c91906141b6565b611c48565b60405161052e91906137cc565b60405180910390f35b610551600480360381019061054c91906141f4565b611cd6565b005b61056d60048036038101906105689190613f3b565b611d7d565b005b610577611e01565b60405161058491906137f4565b60405180910390f35b6105a760048036038101906105a29190613f3b565b611e26565b005b5f60025f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610671575061067082611f3a565b5b9050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060816106a981610d69565b6106ea57806040517fbde6baa50000000000000000000000000000000000000000000000000000000081526004016106e19190613719565b60405180910390fd5b600861070b3073ffffffffffffffffffffffffffffffffffffffff1661201b565b61071485612039565b60405160200161072693929190614444565b604051602081830303815290604052915050919050565b5f600654905090565b5f808261075281610d69565b61079357806040517fbde6baa500000000000000000000000000000000000000000000000000000000815260040161078a9190613719565b60405180910390fd5b6107ac600a5f8681526020019081526020015f20612103565b9250925050915091565b6060816107c281610d69565b61080357806040517fbde6baa50000000000000000000000000000000000000000000000000000000081526004016107fa9190613719565b60405180910390fd5b5f60095f8581526020019081526020015f2054036108315760405180602001604052805f81525091506109ea565b5f61084c60095f8681526020019081526020015f205461201b565b90505f604067ffffffffffffffff81111561086a5761086961398d565b5b6040519080825280601f01601f19166020018201604052801561089c5781602001600182028036833780820191505090505b5090505f825160426108ae91906144b7565b90505f5b818167ffffffffffffffff16101561092557603060f81b838267ffffffffffffffff16815181106108e6576108e56144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053508061091e9061452a565b90506108b2565b505f5b6002845161093691906144b7565b8167ffffffffffffffff1610156109e257836002826109559190614559565b67ffffffffffffffff16815181106109705761096f6144ea565b5b602001015160f81c60f81b83838367ffffffffffffffff166109929190614594565b815181106109a3576109a26144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350806109db9061452a565b9050610928565b508194505050505b50919050565b5f80836109fc81610d69565b610a3d57806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401610a349190613719565b60405180910390fd5b5f600a5f8781526020019081526020015f206040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f820160149054906101000a900460ff1660ff1660ff1681526020015f820160159054906101000a900460ff16151515158152505090508060400151610afb575f809350935050610b38565b5f8503610b1157805f01515f9350935050610b38565b805f0151610b32826020015160ff166064886121429092919063ffffffff16565b93509350505b509250929050565b5f610b49612241565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610b8e5750610b8c8682611c48565b155b15610bd25780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610bc99291906145c7565b60405180910390fd5b610bdf8686868686612248565b505050505050565b5f81610bf281610d69565b610c3357806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401610c2a9190613719565b60405180910390fd5b600a5f8481526020019081526020015f205f0160159054906101000a900460ff16915050919050565b60608151835114610ca857815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610c9f9291906145ee565b60405180910390fd5b5f835167ffffffffffffffff811115610cc457610cc361398d565b5b604051908082528060200260200182016040528015610cf25781602001602082028036833780820191505090505b5090505f5b8451811015610d5e57610d2e610d16828761233c90919063ffffffff16565b610d29838761234f90919063ffffffff16565b6105a9565b828281518110610d4157610d406144ea565b5b60200260200101818152505080610d5790614615565b9050610cf7565b508091505092915050565b5f80610d74836116b0565b119050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e0d57336040517fe5494cc6000000000000000000000000000000000000000000000000000000008152600401610e0491906137f4565b60405180910390fd5b81610e1781610d69565b610e5857806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401610e4f9190613719565b60405180910390fd5b8160095f8581526020019081526020015f205403610ea2576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160095f8581526020019081526020015f208190555081837fc8c7d9aba5aa51ebb81117cf28f9f60ef2bb2b8219fd2dd5dbe3dc7ba9e8a72b60405160405180910390a3505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610f95575060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610fd757336040517fe5494cc6000000000000000000000000000000000000000000000000000000008152600401610fce91906137f4565b60405180910390fd5b5f8585905067ffffffffffffffff811115610ff557610ff461398d565b5b6040519080825280602002602001820160405280156110235781602001602082028036833780820191505090505b5090505f5b8686905081101561114c57611055878783818110611049576110486144ea565b5b90506020020135610d69565b156110b05786868281811061106d5761106c6144ea565b5b905060200201356040517fb1c147ad0000000000000000000000000000000000000000000000000000000081526004016110a79190613719565b60405180910390fd5b60018282815181106110c5576110c46144ea565b5b6020026020010181815250505f8585838181106110e5576110e46144ea565b5b90506020020135111561113b57848482818110611105576111046144ea565b5b9050602002013560095f898985818110611122576111216144ea565b5b9050602002013581526020019081526020015f20819055505b8061114590614615565b9050611028565b506111a7828787808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f820116905080830192505050505050508360405180602001604052805f815250612362565b83836040516111b79291906146ce565b604051809103902086866040516111cf9291906146ce565b60405180910390207f3ea440575b174f0bcd120faa37fac3a98210e03f68a8e3906a6b01d3abc5107760405160405180910390a3505050505050565b6112136123e5565b61121c5f61246c565b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61124d6123e5565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112d3576040517f2264e4cf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132357505f8173ffffffffffffffffffffffffffffffffffffffff163b145b1561136557806040517f288f822800000000000000000000000000000000000000000000000000000000815260040161135c91906137f4565b60405180910390fd5b8060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f027c3e080ed9215f564a9455a666f7e459b3edc0bb6e02a1bf842fde4d0ccfc160405160405180910390a250565b61141e611417612241565b838361252d565b5050565b61142a6123e5565b818160405160200161143d92919061470a565b6040516020818303038152906040528051906020012060086040516020016114659190614722565b60405160208183030381529060405280519060200120036114b2576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181600891826114c39291906148cd565b5081816040516114d492919061470a565b60405180910390207fbf212f907e9933754ffa70bbc0251a1fe289759b6660bff05ba9c028bfda364b60405160405180910390a25050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156115b6575060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156115f857336040517fe5494cc60000000000000000000000000000000000000000000000000000000081526004016115ef91906137f4565b60405180910390fd5b61160183610d69565b1561164357826040517fb1c147ad00000000000000000000000000000000000000000000000000000000815260040161163a9190613719565b60405180910390fd5b5f821115611662578160095f8581526020019081526020015f20819055505b61167d8184600160405180602001604052805f815250612696565b81837fc8c7d9aba5aa51ebb81117cf28f9f60ef2bb2b8219fd2dd5dbe3dc7ba9e8a72b60405160405180910390a3505050565b5f60055f8381526020019081526020015f20549050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461175b57336040517fe5494cc600000000000000000000000000000000000000000000000000000000815260040161175291906137f4565b60405180910390fd5b5f84849050148061176e57505f82829050145b156117a5576040517f8691e5c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181905084849050146117e4576040517f483b9c9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8484905081101561194257611813858583818110611807576118066144ea565b5b90506020020135610d69565b61186d5784848281811061182a576118296144ea565b5b905060200201356040517fbde6baa50000000000000000000000000000000000000000000000000000000081526004016118649190613719565b60405180910390fd5b8282828181106118805761187f6144ea565b5b9050602002013560095f87878581811061189d5761189c6144ea565b5b9050602002013581526020019081526020015f2054036118e9576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8282828181106118fc576118fb6144ea565b5b9050602002013560095f878785818110611919576119186144ea565b5b9050602002013581526020019081526020015f20819055508061193b90614615565b90506117e6565b5081816040516119539291906146ce565b6040518091039020848460405161196b9291906146ce565b60405180910390207f3ea440575b174f0bcd120faa37fac3a98210e03f68a8e3906a6b01d3abc5107760405160405180910390a350505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015611a4f575060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15611a9157336040517fe5494cc6000000000000000000000000000000000000000000000000000000008152600401611a8891906137f4565b60405180910390fd5b82611a9b81610d69565b611adc57806040517fbde6baa5000000000000000000000000000000000000000000000000000000008152600401611ad39190613719565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611b7357600a5f8581526020019081526020015f205f8082015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555f820160146101000a81549060ff02191690555f820160156101000a81549060ff02191690555050611c42565b60405180606001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018360ff16815260200160011515815250600a5f8681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a81548160ff021916908360ff1602179055506040820151815f0160156101000a81548160ff0219169083151502179055509050505b50505050565b5f60035f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f611cdf612241565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015611d245750611d228682611c48565b155b15611d685780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611d5f9291906145c7565b60405180910390fd5b611d75868686868661272b565b505050505050565b611d856123e5565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611df5575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611dec91906137f4565b60405180910390fd5b611dfe8161246c565b50565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611e2e6123e5565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611eb4576040517fa9dce01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fb6b8f1859c5c352e5ffad07d0f77e384ac725512c015bd3a3ffc885831c8a42560405160405180910390a250565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061200457507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612014575061201382612831565b5b9050919050565b606061203282600161202c8561289a565b01612923565b9050919050565b60605f600161204784612b61565b0190505f8167ffffffffffffffff8111156120655761206461398d565b5b6040519080825280601f01601f1916602001820160405280156120975781602001600182028036833780820191505090505b5090505f82602001820190505b6001156120f8578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816120ed576120ec61499a565b5b0494505f85036120a4575b819350505050919050565b5f80825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16835f0160149054906101000a900460ff1691509150915091565b5f8083850290505f8019858709828110838203039150505f810361217a578382816121705761216f61499a565b5b049250505061223a565b8084116121b3576040517f227bc15300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8486880990508281118203915080830392505f855f038616905080860495508084049350600181825f0304019050808302841793505f600287600302189050808702600203810290508087026002038102905080870260020381029050808702600203810290508087026002038102905080870260020381029050808502955050505050505b9392505050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122b8575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016122af91906137f4565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612328575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161231f91906137f4565b60405180910390fd5b6123358585858585612cb2565b5050505050565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036123d2575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016123c991906137f4565b60405180910390fd5b6123df5f85858585612cb2565b50505050565b6123ed612241565b73ffffffffffffffffffffffffffffffffffffffff1661240b61121e565b73ffffffffffffffffffffffffffffffffffffffff161461246a5761242e612241565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161246191906137f4565b60405180910390fd5b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361259d575f6040517fced3e10000000000000000000000000000000000000000000000000000000000815260040161259491906137f4565b60405180910390fd5b8060035f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161268991906137cc565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612706575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016126fd91906137f4565b60405180910390fd5b5f806127128585612d5e565b915091506127235f87848487612cb2565b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361279b575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161279291906137f4565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361280b575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161280291906137f4565b60405180910390fd5b5f806128178585612d5e565b915091506128288787848487612cb2565b50505050505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f805f90505f608084901c11156128b957608083901c92506010810190505b5f604084901c11156128d357604083901c92506008810190505b5f602084901c11156128ed57602083901c92506004810190505b5f601084901c111561290757601083901c92506002810190505b5f600884901c111561291a576001810190505b80915050919050565b60605f8390505f600284600261293991906149c7565b6129439190614594565b67ffffffffffffffff81111561295c5761295b61398d565b5b6040519080825280601f01601f19166020018201604052801561298e5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106129c5576129c46144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612a2857612a276144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f6001856002612a6691906149c7565b612a709190614594565b90505b6001811115612b0f577f3031323334353637383961626364656600000000000000000000000000000000600f841660108110612ab257612ab16144ea565b5b1a60f81b828281518110612ac957612ac86144ea565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c925080612b0890614a08565b9050612a73565b505f8214612b565784846040517fe22e27eb000000000000000000000000000000000000000000000000000000008152600401612b4d9291906145ee565b60405180910390fd5b809250505092915050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612bbd577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612bb357612bb261499a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612bfa576d04ee2d6d415b85acef81000000008381612bf057612bef61499a565b5b0492506020810190505b662386f26fc100008310612c2957662386f26fc100008381612c1f57612c1e61499a565b5b0492506010810190505b6305f5e1008310612c52576305f5e1008381612c4857612c4761499a565b5b0492506008810190505b6127108310612c77576127108381612c6d57612c6c61499a565b5b0492506004810190505b60648310612c9a5760648381612c9057612c8f61499a565b5b0492506002810190505b600a8310612ca9576001810190505b80915050919050565b612cbe85858585612d8e565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612d57575f612cfa612241565b90506001845103612d46575f612d195f8661234f90919063ffffffff16565b90505f612d2f5f8661234f90919063ffffffff16565b9050612d3f838989858589612f37565b5050612d55565b612d548187878787876130e6565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b612d9a84848484613295565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612e73575f805b8351811015612e58575f838281518110612ded57612dec6144ea565b5b602002602001015190508060055f878581518110612e0e57612e0d6144ea565b5b602002602001015181526020019081526020015f205f828254612e319190614594565b925050819055508083612e449190614594565b92505080612e5190614615565b9050612dd0565b508060065f828254612e6a9190614594565b92505081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612f31575f805b8351811015612f1f575f838281518110612ec657612ec56144ea565b5b602002602001015190508060055f878581518110612ee757612ee66144ea565b5b602002602001015181526020019081526020015f205f828254039250508190555080830192505080612f1890614615565b9050612ea9565b508060065f8282540392505081905550505b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b11156130de578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401612f97959493929190614a81565b6020604051808303815f875af1925050508015612fd257506040513d601f19601f82011682018060405250810190612fcf9190614aed565b60015b613053573d805f8114613000576040519150601f19603f3d011682016040523d82523d5f602084013e613005565b606091505b505f81510361304b57846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161304291906137f4565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146130dc57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016130d391906137f4565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561328d578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401613146959493929190614b18565b6020604051808303815f875af192505050801561318157506040513d601f19601f8201168201806040525081019061317e9190614aed565b60015b613202573d805f81146131af576040519150601f19603f3d011682016040523d82523d5f602084013e6131b4565b606091505b505f8151036131fa57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016131f191906137f4565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461328b57846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161328291906137f4565b60405180910390fd5b505b505050505050565b80518251146132df57815181516040517f5b0599910000000000000000000000000000000000000000000000000000000081526004016132d69291906145ee565b60405180910390fd5b5f6132e8612241565b90505f5b83518110156134ed575f613309828661234f90919063ffffffff16565b90505f61331f838661234f90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614613444575f60025f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156133ef57888183856040517f03dee4c50000000000000000000000000000000000000000000000000000000081526004016133e69493929190614b7e565b60405180910390fd5b81810360025f8581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16146134da578060025f8481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546134d29190614594565b925050819055505b5050806134e690614615565b90506132ec565b5060018351036135a8575f61350b5f8561234f90919063ffffffff16565b90505f6135215f8561234f90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516135999291906145ee565b60405180910390a45050613627565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161361e929190614bc1565b60405180910390a45b5050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6136688261363f565b9050919050565b6136788161365e565b8114613682575f80fd5b50565b5f813590506136938161366f565b92915050565b5f819050919050565b6136ab81613699565b81146136b5575f80fd5b50565b5f813590506136c6816136a2565b92915050565b5f80604083850312156136e2576136e1613637565b5b5f6136ef85828601613685565b9250506020613700858286016136b8565b9150509250929050565b61371381613699565b82525050565b5f60208201905061372c5f83018461370a565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61376681613732565b8114613770575f80fd5b50565b5f813590506137818161375d565b92915050565b5f6020828403121561379c5761379b613637565b5b5f6137a984828501613773565b91505092915050565b5f8115159050919050565b6137c6816137b2565b82525050565b5f6020820190506137df5f8301846137bd565b92915050565b6137ee8161365e565b82525050565b5f6020820190506138075f8301846137e5565b92915050565b5f6020828403121561382257613821613637565b5b5f61382f848285016136b8565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561386f578082015181840152602081019050613854565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61389482613838565b61389e8185613842565b93506138ae818560208601613852565b6138b78161387a565b840191505092915050565b5f6020820190508181035f8301526138da818461388a565b905092915050565b5f60ff82169050919050565b6138f7816138e2565b82525050565b5f6040820190506139105f8301856137e5565b61391d60208301846138ee565b9392505050565b5f806040838503121561393a57613939613637565b5b5f613947858286016136b8565b9250506020613958858286016136b8565b9150509250929050565b5f6040820190506139755f8301856137e5565b613982602083018461370a565b9392505050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6139c38261387a565b810181811067ffffffffffffffff821117156139e2576139e161398d565b5b80604052505050565b5f6139f461362e565b9050613a0082826139ba565b919050565b5f67ffffffffffffffff821115613a1f57613a1e61398d565b5b602082029050602081019050919050565b5f80fd5b5f613a46613a4184613a05565b6139eb565b90508083825260208201905060208402830185811115613a6957613a68613a30565b5b835b81811015613a925780613a7e88826136b8565b845260208401935050602081019050613a6b565b5050509392505050565b5f82601f830112613ab057613aaf613989565b5b8135613ac0848260208601613a34565b91505092915050565b5f80fd5b5f67ffffffffffffffff821115613ae757613ae661398d565b5b613af08261387a565b9050602081019050919050565b828183375f83830152505050565b5f613b1d613b1884613acd565b6139eb565b905082815260208101848484011115613b3957613b38613ac9565b5b613b44848285613afd565b509392505050565b5f82601f830112613b6057613b5f613989565b5b8135613b70848260208601613b0b565b91505092915050565b5f805f805f60a08688031215613b9257613b91613637565b5b5f613b9f88828901613685565b9550506020613bb088828901613685565b945050604086013567ffffffffffffffff811115613bd157613bd061363b565b5b613bdd88828901613a9c565b935050606086013567ffffffffffffffff811115613bfe57613bfd61363b565b5b613c0a88828901613a9c565b925050608086013567ffffffffffffffff811115613c2b57613c2a61363b565b5b613c3788828901613b4c565b9150509295509295909350565b5f67ffffffffffffffff821115613c5e57613c5d61398d565b5b602082029050602081019050919050565b5f613c81613c7c84613c44565b6139eb565b90508083825260208201905060208402830185811115613ca457613ca3613a30565b5b835b81811015613ccd5780613cb98882613685565b845260208401935050602081019050613ca6565b5050509392505050565b5f82601f830112613ceb57613cea613989565b5b8135613cfb848260208601613c6f565b91505092915050565b5f8060408385031215613d1a57613d19613637565b5b5f83013567ffffffffffffffff811115613d3757613d3661363b565b5b613d4385828601613cd7565b925050602083013567ffffffffffffffff811115613d6457613d6361363b565b5b613d7085828601613a9c565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613dac81613699565b82525050565b5f613dbd8383613da3565b60208301905092915050565b5f602082019050919050565b5f613ddf82613d7a565b613de98185613d84565b9350613df483613d94565b805f5b83811015613e24578151613e0b8882613db2565b9750613e1683613dc9565b925050600181019050613df7565b5085935050505092915050565b5f6020820190508181035f830152613e498184613dd5565b905092915050565b5f80fd5b5f8083601f840112613e6a57613e69613989565b5b8235905067ffffffffffffffff811115613e8757613e86613e51565b5b602083019150836020820283011115613ea357613ea2613a30565b5b9250929050565b5f805f805f60608688031215613ec357613ec2613637565b5b5f86013567ffffffffffffffff811115613ee057613edf61363b565b5b613eec88828901613e55565b9550955050602086013567ffffffffffffffff811115613f0f57613f0e61363b565b5b613f1b88828901613e55565b93509350506040613f2e88828901613685565b9150509295509295909350565b5f60208284031215613f5057613f4f613637565b5b5f613f5d84828501613685565b91505092915050565b613f6f816137b2565b8114613f79575f80fd5b50565b5f81359050613f8a81613f66565b92915050565b5f8060408385031215613fa657613fa5613637565b5b5f613fb385828601613685565b9250506020613fc485828601613f7c565b9150509250929050565b5f8083601f840112613fe357613fe2613989565b5b8235905067ffffffffffffffff81111561400057613fff613e51565b5b60208301915083600182028301111561401c5761401b613a30565b5b9250929050565b5f806020838503121561403957614038613637565b5b5f83013567ffffffffffffffff8111156140565761405561363b565b5b61406285828601613fce565b92509250509250929050565b5f805f6060848603121561408557614084613637565b5b5f614092868287016136b8565b93505060206140a3868287016136b8565b92505060406140b486828701613685565b9150509250925092565b5f805f80604085870312156140d6576140d5613637565b5b5f85013567ffffffffffffffff8111156140f3576140f261363b565b5b6140ff87828801613e55565b9450945050602085013567ffffffffffffffff8111156141225761412161363b565b5b61412e87828801613e55565b925092505092959194509250565b614145816138e2565b811461414f575f80fd5b50565b5f813590506141608161413c565b92915050565b5f805f6060848603121561417d5761417c613637565b5b5f61418a868287016136b8565b935050602061419b86828701613685565b92505060406141ac86828701614152565b9150509250925092565b5f80604083850312156141cc576141cb613637565b5b5f6141d985828601613685565b92505060206141ea85828601613685565b9150509250929050565b5f805f805f60a0868803121561420d5761420c613637565b5b5f61421a88828901613685565b955050602061422b88828901613685565b945050604061423c888289016136b8565b935050606061424d888289016136b8565b925050608086013567ffffffffffffffff81111561426e5761426d61363b565b5b61427a88828901613b4c565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806142cb57607f821691505b6020821081036142de576142dd614287565b5b50919050565b5f81905092915050565b5f819050815f5260205f209050919050565b5f815461430c816142b4565b61431681866142e4565b9450600182165f8114614330576001811461434557614377565b60ff1983168652811515820286019350614377565b61434e856142ee565b5f5b8381101561436f57815481890152600182019150602081019050614350565b838801955050505b50505092915050565b5f61438a82613838565b61439481856142e4565b93506143a4818560208601613852565b80840191505092915050565b7f2f000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6143e46001836142e4565b91506143ef826143b0565b600182019050919050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61442e6005836142e4565b9150614439826143fa565b600582019050919050565b5f61444f8286614300565b915061445b8285614380565b9150614466826143d8565b91506144728284614380565b915061447d82614422565b9150819050949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6144c182613699565b91506144cc83613699565b92508282039050818111156144e4576144e361448a565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f67ffffffffffffffff82169050919050565b5f61453482614517565b915067ffffffffffffffff820361454e5761454d61448a565b5b600182019050919050565b5f61456382614517565b915061456e83614517565b9250828201905067ffffffffffffffff81111561458e5761458d61448a565b5b92915050565b5f61459e82613699565b91506145a983613699565b92508282019050808211156145c1576145c061448a565b5b92915050565b5f6040820190506145da5f8301856137e5565b6145e760208301846137e5565b9392505050565b5f6040820190506146015f83018561370a565b61460e602083018461370a565b9392505050565b5f61461f82613699565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146515761465061448a565b5b600182019050919050565b5f81905092915050565b5f80fd5b82818337505050565b5f61467e838561465c565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156146b1576146b0614666565b5b6020830292506146c283858461466a565b82840190509392505050565b5f6146da828486614673565b91508190509392505050565b5f6146f183856142e4565b93506146fe838584613afd565b82840190509392505050565b5f6147168284866146e6565b91508190509392505050565b5f61472d8284614300565b915081905092915050565b5f82905092915050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261478c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614751565b6147968683614751565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6147d16147cc6147c784613699565b6147ae565b613699565b9050919050565b5f819050919050565b6147ea836147b7565b6147fe6147f6826147d8565b84845461475d565b825550505050565b5f90565b614812614806565b61481d8184846147e1565b505050565b5b81811015614840576148355f8261480a565b600181019050614823565b5050565b601f82111561488557614856816142ee565b61485f84614742565b8101602085101561486e578190505b61488261487a85614742565b830182614822565b50505b505050565b5f82821c905092915050565b5f6148a55f198460080261488a565b1980831691505092915050565b5f6148bd8383614896565b9150826002028217905092915050565b6148d78383614738565b67ffffffffffffffff8111156148f0576148ef61398d565b5b6148fa82546142b4565b614905828285614844565b5f601f831160018114614932575f8415614920578287013590505b61492a85826148b2565b865550614991565b601f198416614940866142ee565b5f5b8281101561496757848901358255600182019150602085019450602081019050614942565b868310156149845784890135614980601f891682614896565b8355505b6001600288020188555050505b50505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6149d182613699565b91506149dc83613699565b92508282026149ea81613699565b91508282048414831517614a0157614a0061448a565b5b5092915050565b5f614a1282613699565b91505f8203614a2457614a2361448a565b5b600182039050919050565b5f81519050919050565b5f82825260208201905092915050565b5f614a5382614a2f565b614a5d8185614a39565b9350614a6d818560208601613852565b614a768161387a565b840191505092915050565b5f60a082019050614a945f8301886137e5565b614aa160208301876137e5565b614aae604083018661370a565b614abb606083018561370a565b8181036080830152614acd8184614a49565b90509695505050505050565b5f81519050614ae78161375d565b92915050565b5f60208284031215614b0257614b01613637565b5b5f614b0f84828501614ad9565b91505092915050565b5f60a082019050614b2b5f8301886137e5565b614b3860208301876137e5565b8181036040830152614b4a8186613dd5565b90508181036060830152614b5e8185613dd5565b90508181036080830152614b728184614a49565b90509695505050505050565b5f608082019050614b915f8301876137e5565b614b9e602083018661370a565b614bab604083018561370a565b614bb8606083018461370a565b95945050505050565b5f6040820190508181035f830152614bd98185613dd5565b90508181036020830152614bed8184613dd5565b9050939250505056fea26469706673582212204663c8f2a003d356b3ae3c524b082d5ed7e152a008b25704ce6ceb0b7942b61464736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6e66742e736d617274766572756d2e636f6d2f76612f706f6c79676f6e2f0000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : uriPrefix (string): https://nft.smartverum.com/va/polygon/
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000026
Arg [2] : 68747470733a2f2f6e66742e736d617274766572756d2e636f6d2f76612f706f
Arg [3] : 6c79676f6e2f0000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
93915:9852:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73795:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103532:232;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94186:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;101103:245;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;89972:102;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;102481:174;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;101437:660;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;102722:461;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;75618:441;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;103297:163;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;74095:567;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;90172:108;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98949:344;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;97740:706;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3281:103;;;:::i;:::-;;2606:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93394:419;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;74735:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;98526:323;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;97106:442;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;89797:113;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99396:835;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;100356:355;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;74953:159;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;75184:357;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3539:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;92055:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100786:233;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;73795:134;73872:7;73899:9;:13;73909:2;73899:13;;;;;;;;;;;:22;73913:7;73899:22;;;;;;;;;;;;;;;;73892:29;;73795:134;;;;:::o;103532:232::-;103635:4;103682:26;103659:49;;;:19;:49;;;;:97;;;;103712:44;103736:19;103712:23;:44::i;:::-;103659:97;103652:104;;103532:232;;;:::o;94186:21::-;;;;;;;;;;;;;:::o;101103:245::-;101196:13;101175:10;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;101253:10:::1;101265:36;101281:4;101265:34;;;:36::i;:::-;101308:21;:10;:19;:21::i;:::-;101236:103;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;101222:118;;101103:245:::0;;;;:::o;89972:102::-;90024:7;90051:15;;90044:22;;89972:102;:::o;102481:174::-;102576:7;102585:5;102555:10;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;102610:37:::1;102619:15;:27;102635:10;102619:27;;;;;;;;;;;102610:8;:37::i;:::-;102603:44;;;;102481:174:::0;;;;:::o;101437:660::-;101536:13;101515:10;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;101592:1:::1;101566:10;:22;101577:10;101566:22;;;;;;;;;;;;:27:::0;101562:69:::1;;101610:9;;;;;;;;;;;::::0;::::1;;;;101562:69;101643:22;101674:36;:10;:22;101685:10;101674:22;;;;;;;;;;;;:34;:36::i;:::-;101643:68;;101722:27;101762:2;101752:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101722:43;;101776:14;101798:9;:16;101793:2;:21;;;;:::i;:::-;101776:38;;101832:8;101827:87;101850:6;101846:1;:10;;;101827:87;;;101898:4;101878:24;;:14;101893:1;101878:17;;;;;;;;;;:::i;:::-;;;;;:24;;;;;;;;;;;101858:3;;;;:::i;:::-;;;101827:87;;;;101931:8;101926:122;101968:1;101949:9;:16;:20;;;;:::i;:::-;101945:1;:24;;;101926:122;;;102020:9;102034:1;102030;:5;;;;:::i;:::-;102020:16;;;;;;;;;;:::i;:::-;;;;;;;;;;101991:14;102010:6;102006:1;:10;;;;;;:::i;:::-;101991:26;;;;;;;;:::i;:::-;;;;;:45;;;;;;;;;;;101971:3;;;;:::i;:::-;;;101926:122;;;;102074:14;102060:29;;;;;96919:1;101437:660:::0;;;;:::o;102722:461::-;102842:7;102851;102821:10;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;102871:22:::1;102896:15;:27;102912:10;102896:27;;;;;;;;;;;102871:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;102941:7;:13;;;102936:69;;102987:1;102991::::0;102971:22:::1;;;;;;;102936:69;103034:1;103021:9;:14:::0;103017:78:::1;;103060:7;:19;;;103081:1;103052:31;;;;;;;103017:78;103115:7;:19;;;103136:38;103153:7;:15;;;103136:38;;103170:3;103136:9;:16;;:38;;;;;:::i;:::-;103107:68;;;;;96919:1;102722:461:::0;;;;;;:::o;75618:441::-;75819:14;75836:12;:10;:12::i;:::-;75819:29;;75871:6;75863:14;;:4;:14;;;;:49;;;;;75882:30;75899:4;75905:6;75882:16;:30::i;:::-;75881:31;75863:49;75859:131;;;75965:6;75973:4;75936:42;;;;;;;;;;;;:::i;:::-;;;;;;;;75859:131;76000:51;76023:4;76029:2;76033:3;76038:6;76046:4;76000:22;:51::i;:::-;75808:251;75618:441;;;;;:::o;103297:163::-;103395:4;103374:10;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;103419:15:::1;:27;103435:10;103419:27;;;;;;;;;;;:33;;;;;;;;;;;;103412:40;;103297:163:::0;;;;:::o;74095:567::-;74222:16;74274:3;:10;74255:8;:15;:29;74251:123;;74334:3;:10;74346:8;:15;74308:54;;;;;;;;;;;;:::i;:::-;;;;;;;;74251:123;74386:30;74433:8;:15;74419:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74386:63;;74467:9;74462:160;74486:8;:15;74482:1;:19;74462:160;;;74542:68;74552:30;74580:1;74552:8;:27;;:30;;;;:::i;:::-;74584:25;74607:1;74584:3;:22;;:25;;;;:::i;:::-;74542:9;:68::i;:::-;74523:13;74537:1;74523:16;;;;;;;;:::i;:::-;;;;;;;:87;;;;;74503:3;;;;:::i;:::-;;;74462:160;;;;74641:13;74634:20;;;74095:567;;;;:::o;90172:108::-;90229:4;90271:1;90253:15;90265:2;90253:11;:15::i;:::-;:19;90246:26;;90172:108;;;:::o;98949:344::-;96549:6;;;;;;;;;;;96535:20;;:10;:20;;;96531:103;;96611:10;96579:43;;;;;;;;;;;:::i;:::-;;;;;;;;96531:103;99054:10:::1;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;99107:8:::2;99081:10;:22;99092:10;99081:22;;;;;;;;;;;;:34:::0;99077:100:::2;;99139:26;;;;;;;;;;;;;;99077:100;99214:8;99189:10;:22;99200:10;99189:22;;;;;;;;;;;:33;;;;99276:8;99264:10;99240:45;;;;;;;;;;96644:1:::1;98949:344:::0;;:::o;97740:706::-;96272:10;;;;;;;;;;;96258:24;;:10;:24;;;;:48;;;;;96300:6;;;;;;;;;;;96286:20;;:10;:20;;;;96258:48;96254:131;;;96362:10;96330:43;;;;;;;;;;;:::i;:::-;;;;;;;;96254:131;97896:23:::1;97936:11;;:18;;97922:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97896:59;;97973:9;97968:340;97992:11;;:18;;97988:1;:22;97968:340;;;98036:22;98043:11;;98055:1;98043:14;;;;;;;:::i;:::-;;;;;;;;98036:6;:22::i;:::-;98032:121;;;98122:11;;98134:1;98122:14;;;;;;;:::i;:::-;;;;;;;;98086:51;;;;;;;;;;;:::i;:::-;;;;;;;;98032:121;98181:1;98169:6;98176:1;98169:9;;;;;;;;:::i;:::-;;;;;;;:13;;;::::0;::::1;98218:1;98203:9;;98213:1;98203:12;;;;;;;:::i;:::-;;;;;;;;:16;98199:98;;;98269:9;;98279:1;98269:12;;;;;;;:::i;:::-;;;;;;;;98240:10;:26;98251:11;;98263:1;98251:14;;;;;;;:::i;:::-;;;;;;;;98240:26;;;;;;;;;;;:41;;;;98199:98;98012:3;;;;:::i;:::-;;;97968:340;;;;98320:48;98331:11;98344;;98320:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98357:6;98320:48;;;;;;;;;;;::::0;:10:::1;:48::i;:::-;98428:9;;98386:52;;;;;;;:::i;:::-;;;;;;;;98415:11;;98386:52;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;97885:561;97740:706:::0;;;;;:::o;3281:103::-;2492:13;:11;:13::i;:::-;3346:30:::1;3373:1;3346:18;:30::i;:::-;3281:103::o:0;2606:87::-;2652:7;2679:6;;;;;;;;;;;2672:13;;2606:87;:::o;93394:419::-;2492:13;:11;:13::i;:::-;93491:10:::1;;;;;;;;;;;93474:27;;:13;:27;;::::0;93470:93:::1;;93525:26;;;;;;;;;;;;;;93470:93;93604:1;93579:27;;:13;:27;;;:61;;;;93639:1;93610:13;:25;;;:30;93579:61;93575:145;;;93694:13;93664:44;;;;;;;;;;;:::i;:::-;;;;;;;;93575:145;93745:13;93732:10;;:26;;;;;;;;;;;;;;;;;;93794:10;;;;;;;;;;;93776:29;;;;;;;;;;;;93394:419:::0;:::o;74735:146::-;74821:52;74840:12;:10;:12::i;:::-;74854:8;74864;74821:18;:52::i;:::-;74735:146;;:::o;98526:323::-;2492:13;:11;:13::i;:::-;98687:9:::1;;98670:27;;;;;;;;;:::i;:::-;;;;;;;;;;;;;98660:38;;;;;;98644:10;98627:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;98617:39;;;;;;:81:::0;98613:147:::1;;98722:26;;;;;;;;;;;;;;98613:147;98785:9;;98772:10;:22;;;;;;;:::i;:::-;;98831:9;;98812:29;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;98526:323:::0;;:::o;97106:442::-;96272:10;;;;;;;;;;;96258:24;;:10;:24;;;;:48;;;;;96300:6;;;;;;;;;;;96286:20;;:10;:20;;;;96258:48;96254:131;;;96362:10;96330:43;;;;;;;;;;;:::i;:::-;;;;;;;;96254:131;97237:18:::1;97244:10;97237:6;:18::i;:::-;97233:105;;;97315:10;97279:47;;;;;;;;;;;:::i;:::-;;;;;;;;97233:105;97365:1;97354:8;:12;97350:78;;;97408:8;97383:10;:22;97394:10;97383:22;;;;;;;;;;;:33;;;;97350:78;97440:37;97446:11;97459:10;97471:1;97440:37;;;;;;;;;;;::::0;:5:::1;:37::i;:::-;97531:8;97519:10;97495:45;;;;;;;;;;97106:442:::0;;;:::o;89797:113::-;89859:7;89886:12;:16;89899:2;89886:16;;;;;;;;;;;;89879:23;;89797:113;;;:::o;99396:835::-;96549:6;;;;;;;;;;;96535:20;;:10;:20;;;96531:103;;96611:10;96579:43;;;;;;;;;;;:::i;:::-;;;;;;;;96531:103;99549:1:::1;99527:11;;:18;;:23;:48;;;;99574:1;99554:9;;:16;;:21;99527:48;99523:111;;;99599:23;;;;;;;;;;;;;;99523:111;99672:9;;:16;;99650:11;;:18;;:38;99646:111;;99712:33;;;;;;;;;;;;;;99646:111;99774:9;99769:385;99793:11;;:18;;99789:1;:22;99769:385;;;99838:22;99845:11;;99857:1;99845:14;;;;;;;:::i;:::-;;;;;;;;99838:6;:22::i;:::-;99833:121;;99923:11;;99935:1;99923:14;;;;;;;:::i;:::-;;;;;;;;99888:50;;;;;;;;;;;:::i;:::-;;;;;;;;99833:121;100004:9;;100014:1;100004:12;;;;;;;:::i;:::-;;;;;;;;99974:10;:26;99985:11;;99997:1;99985:14;;;;;;;:::i;:::-;;;;;;;;99974:26;;;;;;;;;;;;:42:::0;99970:116:::1;;100044:26;;;;;;;;;;;;;;99970:116;100130:9;;100140:1;100130:12;;;;;;;:::i;:::-;;;;;;;;100101:10;:26;100112:11;;100124:1;100112:14;;;;;;;:::i;:::-;;;;;;;;100101:26;;;;;;;;;;;:41;;;;99813:3;;;;:::i;:::-;;;99769:385;;;;100213:9;;100171:52;;;;;;;:::i;:::-;;;;;;;;100200:11;;100171:52;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;99396:835:::0;;;;:::o;100356:355::-;96272:10;;;;;;;;;;;96258:24;;:10;:24;;;;:48;;;;;96300:6;;;;;;;;;;;96286:20;;:10;:20;;;;96258:48;96254:131;;;96362:10;96330:43;;;;;;;;;;;:::i;:::-;;;;;;;;96254:131;100491:10:::1;96809:18;96816:10;96809:6;:18::i;:::-;96804:105;;96886:10;96851:46;;;;;;;;;;;:::i;:::-;;;;;;;;96804:105;100541:1:::2;100518:25;;:11;:25;;::::0;100514:190:::2;;100567:15;:27;100583:10;100567:27;;;;;;;;;;;;100560:34:::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100514:190;;;100657:35;;;;;;;;100665:11;100657:35;;;;;;100678:7;100657:35;;;;;;100687:4;100657:35;;;;::::0;100627:15:::2;:27;100643:10;100627:27;;;;;;;;;;;:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100514:190;96395:1:::1;100356:355:::0;;;:::o;74953:159::-;75043:4;75067:18;:27;75086:7;75067:27;;;;;;;;;;;;;;;:37;75095:8;75067:37;;;;;;;;;;;;;;;;;;;;;;;;;75060:44;;74953:159;;;;:::o;75184:357::-;75308:14;75325:12;:10;:12::i;:::-;75308:29;;75360:6;75352:14;;:4;:14;;;;:49;;;;;75371:30;75388:4;75394:6;75371:16;:30::i;:::-;75370:31;75352:49;75348:131;;;75454:6;75462:4;75425:42;;;;;;;;;;;;:::i;:::-;;;;;;;;75348:131;75489:44;75507:4;75513:2;75517;75521:5;75528:4;75489:17;:44::i;:::-;75297:244;75184:357;;;;;:::o;3539:220::-;2492:13;:11;:13::i;:::-;3644:1:::1;3624:22;;:8;:22;;::::0;3620:93:::1;;3698:1;3670:31;;;;;;;;;;;:::i;:::-;;;;;;;;3620:93;3723:28;3742:8;3723:18;:28::i;:::-;3539:220:::0;:::o;92055:25::-;;;;;;;;;;;;;:::o;100786:233::-;2492:13;:11;:13::i;:::-;100871:6:::1;;;;;;;;;;;100858:19;;:9;:19;;::::0;100854:85:::1;;100901:26;;;;;;;;;;;;;;100854:85;100960:9;100951:6;;:18;;;;;;;;;;;;;;;;;;101001:9;100987:24;;;;;;;;;;;;100786:233:::0;:::o;72904:310::-;73006:4;73058:26;73043:41;;;:11;:41;;;;:110;;;;73116:37;73101:52;;;:11;:52;;;;73043:110;:163;;;;73170:36;73194:11;73170:23;:36::i;:::-;73043:163;73023:183;;72904:310;;;:::o;33276:178::-;33335:13;33393:42;33405:5;33433:1;33412:18;33424:5;33412:11;:18::i;:::-;:22;33393:11;:42::i;:::-;33386:49;;33276:178;;;:::o;32173:718::-;32229:13;32280:14;32317:1;32297:17;32308:5;32297:10;:17::i;:::-;:21;32280:38;;32333:20;32367:6;32356:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32333:41;;32389:11;32518:6;32514:2;32510:15;32502:6;32498:28;32491:35;;32555:290;32562:4;32555:290;;;32587:5;;;;;;;;32729:10;32724:2;32717:5;32713:14;32708:32;32703:3;32695:46;32787:2;32778:11;;;;;;:::i;:::-;;;;;32821:1;32812:5;:10;32555:290;32808:21;32555:290;32866:6;32859:13;;;;;32173:718;;;:::o;102189:146::-;102255:7;102264:5;102290:7;:19;;;;;;;;;;;;102311:7;:15;;;;;;;;;;;;102282:45;;;;102189:146;;;:::o;18752:4195::-;18834:14;19186:13;19206:1;19202;:5;19186:21;;19267:13;19394:1;19390:6;19387:1;19384;19377:20;19451:5;19447:2;19444:13;19436:5;19432:2;19428:14;19424:34;19415:43;;19348:125;19566:1;19557:5;:10;19553:373;;19899:11;19891:5;:19;;;;;:::i;:::-;;;19884:26;;;;;;19553:373;20050:5;20035:11;:20;20031:90;;20083:22;;;;;;;;;;;;;;20031:90;20383:17;20521:11;20518:1;20515;20508:25;20495:38;;20652:5;20641:9;20638:20;20631:5;20627:32;20618:41;;20697:9;20690:5;20686:21;20677:30;;20931:12;20965:11;20961:1;:15;20946:11;:31;20931:46;;21100:4;21087:11;21083:22;21068:37;;21195:4;21188:5;21184:16;21175:25;;21355:1;21348:4;21341;21338:1;21334:12;21330:23;21326:31;21318:39;;21458:4;21450:5;:12;21441:21;;;;21785:15;21823:1;21808:11;21804:1;:15;21803:21;21785:39;;22074:7;22060:11;:21;22056:1;:25;22045:36;;;;22144:7;22130:11;:21;22126:1;:25;22115:36;;;;22215:7;22201:11;:21;22197:1;:25;22186:36;;;;22286:7;22272:11;:21;22268:1;:25;22257:36;;;;22357:7;22343:11;:21;22339:1;:25;22328:36;;;;22429:7;22415:11;:21;22411:1;:25;22400:36;;;;22893:7;22885:5;:15;22876:24;;22915:13;;;;;18752:4195;;;;;;:::o;674:98::-;727:7;754:10;747:17;;674:98;:::o;80746:459::-;80960:1;80946:16;;:2;:16;;;80942:90;;81017:1;80986:34;;;;;;;;;;;:::i;:::-;;;;;;;;80942:90;81062:1;81046:18;;:4;:18;;;81042:90;;81117:1;81088:32;;;;;;;;;;;:::i;:::-;;;;;;;;81042:90;81142:55;81169:4;81175:2;81179:3;81184:6;81192:4;81142:26;:55::i;:::-;80746:459;;;;;:::o;65061:201::-;65147:11;65237:4;65232:3;65228:14;65221:4;65216:3;65212:14;65208:35;65202:42;65195:49;;65061:201;;;;:::o;64651:::-;64737:11;64827:4;64822:3;64818:14;64811:4;64806:3;64802:14;64798:35;64792:42;64785:49;;64651:201;;;;:::o;83324:287::-;83460:1;83446:16;;:2;:16;;;83442:90;;83517:1;83486:34;;;;;;;;;;;:::i;:::-;;;;;;;;83442:90;83542:61;83577:1;83581:2;83585:3;83590:6;83598:4;83542:26;:61::i;:::-;83324:287;;;;:::o;2771:166::-;2842:12;:10;:12::i;:::-;2831:23;;:7;:5;:7::i;:::-;:23;;;2827:103;;2905:12;:10;:12::i;:::-;2878:40;;;;;;;;;;;:::i;:::-;;;;;;;;2827:103;2771:166::o;3919:191::-;3993:16;4012:6;;;;;;;;;;;3993:25;;4038:8;4029:6;;:17;;;;;;;;;;;;;;;;;;4093:8;4062:40;;4083:8;4062:40;;;;;;;;;;;;3982:128;3919:191;:::o;85121:321::-;85249:1;85229:22;;:8;:22;;;85225:96;;85306:1;85275:34;;;;;;;;;;;:::i;:::-;;;;;;;;85225:96;85369:8;85331:18;:25;85350:5;85331:25;;;;;;;;;;;;;;;:35;85357:8;85331:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;85415:8;85393:41;;85408:5;85393:41;;;85425:8;85393:41;;;;;;:::i;:::-;;;;;;;;85121:321;;;:::o;82527:352::-;82638:1;82624:16;;:2;:16;;;82620:90;;82695:1;82664:34;;;;;;;;;;;:::i;:::-;;;;;;;;82620:90;82721:20;82743:23;82770:29;82789:2;82793:5;82770:18;:29::i;:::-;82720:79;;;;82810:61;82845:1;82849:2;82853:3;82858:6;82866:4;82810:26;:61::i;:::-;82609:270;;82527:352;;;;:::o;79860:472::-;79997:1;79983:16;;:2;:16;;;79979:90;;80054:1;80023:34;;;;;;;;;;;:::i;:::-;;;;;;;;79979:90;80099:1;80083:18;;:4;:18;;;80079:90;;80154:1;80125:32;;;;;;;;;;;:::i;:::-;;;;;;;;80079:90;80180:20;80202:23;80229:29;80248:2;80252:5;80229:18;:29::i;:::-;80179:79;;;;80269:55;80296:4;80302:2;80306:3;80311:6;80319:4;80269:26;:55::i;:::-;79968:364;;79860:472;;;;;:::o;56269:148::-;56345:4;56384:25;56369:40;;;:11;:40;;;;56362:47;;56269:148;;;:::o;28990:687::-;29044:7;29064:14;29081:1;29064:18;;29137:1;29131:3;29122:5;:12;;:16;29118:101;;;29169:3;29159:13;;;;;29201:2;29191:12;;;;29118:101;29251:1;29246:2;29237:5;:11;;:15;29233:98;;;29283:2;29273:12;;;;;29314:1;29304:11;;;;29233:98;29363:1;29358:2;29349:5;:11;;:15;29345:98;;;29395:2;29385:12;;;;;29426:1;29416:11;;;;29345:98;29475:1;29470:2;29461:5;:11;;:15;29457:98;;;29507:2;29497:12;;;;;29538:1;29528:11;;;;29457:98;29586:1;29582;29573:5;:10;;:14;29569:66;;;29618:1;29608:11;;;;29569:66;29663:6;29656:13;;;28990:687;;;:::o;33582:538::-;33657:13;33683:18;33704:5;33683:26;;33720:19;33765:1;33756:6;33752:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;33742:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33720:47;;33778:15;:6;33785:1;33778:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;33804;:6;33811:1;33804:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;33835:9;33860:1;33851:6;33847:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;33835:26;;33830:143;33867:1;33863;:5;33830:143;;;33902:10;33926:3;33913:10;:16;33902:28;;;;;;;:::i;:::-;;;;;33890:6;33897:1;33890:9;;;;;;;;:::i;:::-;;;;;:40;;;;;;;;;;;33960:1;33945:16;;;;;33870:3;;;;:::i;:::-;;;33830:143;;;;34001:1;33987:10;:15;33983:98;;34055:5;34062:6;34026:43;;;;;;;;;;;;:::i;:::-;;;;;;;;33983:98;34105:6;34091:21;;;;33582:538;;;;:::o;27361:948::-;27414:7;27434:14;27451:1;27434:18;;27501:8;27492:5;:17;27488:106;;27539:8;27530:17;;;;;;:::i;:::-;;;;;27576:2;27566:12;;;;27488:106;27621:8;27612:5;:17;27608:106;;27659:8;27650:17;;;;;;:::i;:::-;;;;;27696:2;27686:12;;;;27608:106;27741:8;27732:5;:17;27728:106;;27779:8;27770:17;;;;;;:::i;:::-;;;;;27816:2;27806:12;;;;27728:106;27861:7;27852:5;:16;27848:103;;27898:7;27889:16;;;;;;:::i;:::-;;;;;27934:1;27924:11;;;;27848:103;27978:7;27969:5;:16;27965:103;;28015:7;28006:16;;;;;;:::i;:::-;;;;;28051:1;28041:11;;;;27965:103;28095:7;28086:5;:16;28082:103;;28132:7;28123:16;;;;;;:::i;:::-;;;;;28168:1;28158:11;;;;28082:103;28212:7;28203:5;:16;28199:68;;28250:1;28240:11;;;;28199:68;28295:6;28288:13;;;27361:948;;;:::o;78681:708::-;78889:30;78897:4;78903:2;78907:3;78912:6;78889:7;:30::i;:::-;78948:1;78934:16;;:2;:16;;;78930:452;;78967:16;78986:12;:10;:12::i;:::-;78967:31;;79031:1;79017:3;:10;:15;79013:358;;79053:10;79066:25;79089:1;79066:3;:22;;:25;;;;:::i;:::-;79053:38;;79110:13;79126:28;79152:1;79126:6;:25;;:28;;;;:::i;:::-;79110:44;;79173:67;79204:8;79214:4;79220:2;79224;79228:5;79235:4;79173:30;:67::i;:::-;79034:222;;79013:358;;;79281:74;79317:8;79327:4;79333:2;79337:3;79342:6;79350:4;79281:35;:74::i;:::-;79013:358;78952:430;78930:452;78681:708;;;;;:::o;88010:870::-;88121:23;88146;88311:4;88305:11;88295:21;;88383:1;88375:6;88368:17;88523:8;88516:4;88508:6;88504:17;88497:35;88648:4;88640:6;88636:17;88626:27;;88682:1;88674:6;88667:17;88724:8;88717:4;88709:6;88705:17;88698:35;88856:4;88848:6;88844:17;88838:4;88831:31;88010:870;;;;;:::o;90342:1555::-;90512:36;90526:4;90532:2;90536:3;90541:6;90512:13;:36::i;:::-;90581:1;90565:18;;:4;:18;;;90561:543;;90600:22;90646:9;90641:298;90665:3;:10;90661:1;:14;90641:298;;;90701:13;90717:6;90724:1;90717:9;;;;;;;;:::i;:::-;;;;;;;;90701:25;;90876:5;90852:12;:20;90865:3;90869:1;90865:6;;;;;;;;:::i;:::-;;;;;;;;90852:20;;;;;;;;;;;;:29;;;;;;;:::i;:::-;;;;;;;;90918:5;90900:23;;;;;:::i;:::-;;;90682:257;90677:3;;;;:::i;:::-;;;90641:298;;;;91078:14;91059:15;;:33;;;;;;;:::i;:::-;;;;;;;;90585:519;90561:543;91134:1;91120:16;;:2;:16;;;91116:774;;91153:22;91199:9;91194:468;91218:3;:10;91214:1;:14;91194:468;;;91254:13;91270:6;91277:1;91270:9;;;;;;;;:::i;:::-;;;;;;;;91254:25;;91464:5;91440:12;:20;91453:3;91457:1;91453:6;;;;;;;;:::i;:::-;;;;;;;;91440:20;;;;;;;;;;;;:29;;;;;;;;;;;91622:5;91604:23;;;;91235:427;91230:3;;;;:::i;:::-;;;91194:468;;;;91849:14;91830:15;;:33;;;;;;;;;;;91138:752;91116:774;90342:1555;;;;:::o;85626:1000::-;85857:1;85840:2;:14;;;:18;85836:783;;;85896:2;85879:38;;;85918:8;85928:4;85934:2;85938:5;85945:4;85879:71;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;85875:733;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86257:1;86240:6;:13;:18;86236:357;;86369:2;86346:26;;;;;;;;;;;:::i;:::-;;;;;;;;86236:357;86543:6;86537:13;86528:6;86524:2;86520:15;86513:38;85875:733;86012:43;;;86000:55;;;:8;:55;;;;85996:177;;86150:2;86127:26;;;;;;;;;;;:::i;:::-;;;;;;;;85996:177;85951:237;85836:783;85626:1000;;;;;;:::o;86820:1069::-;87076:1;87059:2;:14;;;:18;87055:827;;;87115:2;87098:43;;;87142:8;87152:4;87158:3;87163:6;87171:4;87098:78;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;87094:777;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87520:1;87503:6;:13;:18;87499:357;;87632:2;87609:26;;;;;;;;;;;:::i;:::-;;;;;;;;87499:357;87806:6;87800:13;87791:6;87787:2;87783:15;87776:38;87094:777;87270:48;;;87258:60;;;:8;:60;;;;87254:182;;87413:2;87390:26;;;;;;;;;;;:::i;:::-;;;;;;;;87254:182;87177:274;87055:827;86820:1069;;;;;;:::o;76776:1315::-;76912:6;:13;76898:3;:10;:27;76894:119;;76975:3;:10;76987:6;:13;76949:52;;;;;;;;;;;;:::i;:::-;;;;;;;;76894:119;77025:16;77044:12;:10;:12::i;:::-;77025:31;;77074:9;77069:709;77093:3;:10;77089:1;:14;77069:709;;;77125:10;77138:25;77161:1;77138:3;:22;;:25;;;;:::i;:::-;77125:38;;77178:13;77194:28;77220:1;77194:6;:25;;:28;;;;:::i;:::-;77178:44;;77259:1;77243:18;;:4;:18;;;77239:429;;77282:19;77304:9;:13;77314:2;77304:13;;;;;;;;;;;:19;77318:4;77304:19;;;;;;;;;;;;;;;;77282:41;;77360:5;77346:11;:19;77342:131;;;77424:4;77430:11;77443:5;77450:2;77397:56;;;;;;;;;;;;;;:::i;:::-;;;;;;;;77342:131;77628:5;77614:11;:19;77592:9;:13;77602:2;77592:13;;;;;;;;;;;:19;77606:4;77592:19;;;;;;;;;;;;;;;:41;;;;77263:405;77239:429;77702:1;77688:16;;:2;:16;;;77684:83;;77746:5;77725:9;:13;77735:2;77725:13;;;;;;;;;;;:17;77739:2;77725:17;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;77684:83;77110:668;;77105:3;;;;:::i;:::-;;;77069:709;;;;77808:1;77794:3;:10;:15;77790:294;;77826:10;77839:25;77862:1;77839:3;:22;;:25;;;;:::i;:::-;77826:38;;77879:13;77895:28;77921:1;77895:6;:25;;:28;;;;:::i;:::-;77879:44;;77974:2;77943:45;;77968:4;77943:45;;77958:8;77943:45;;;77978:2;77982:5;77943:45;;;;;;;:::i;:::-;;;;;;;;77811:189;;77790:294;;;78056:2;78026:46;;78050:4;78026:46;;78040:8;78026:46;;;78060:3;78065:6;78026:46;;;;;;;:::i;:::-;;;;;;;;77790:294;76883:1208;76776:1315;;;;:::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:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:139::-;742:5;780:6;767:20;758:29;;796:33;823:5;796:33;:::i;:::-;696:139;;;;:::o;841:77::-;878:7;907:5;896:16;;841:77;;;:::o;924:122::-;997:24;1015:5;997:24;:::i;:::-;990:5;987:35;977:63;;1036:1;1033;1026:12;977:63;924:122;:::o;1052:139::-;1098:5;1136:6;1123:20;1114:29;;1152:33;1179:5;1152:33;:::i;:::-;1052:139;;;;:::o;1197:474::-;1265:6;1273;1322:2;1310:9;1301:7;1297:23;1293:32;1290:119;;;1328:79;;:::i;:::-;1290:119;1448:1;1473:53;1518:7;1509:6;1498:9;1494:22;1473:53;:::i;:::-;1463:63;;1419:117;1575:2;1601:53;1646:7;1637:6;1626:9;1622:22;1601:53;:::i;:::-;1591:63;;1546:118;1197:474;;;;;:::o;1677:118::-;1764:24;1782:5;1764:24;:::i;:::-;1759:3;1752:37;1677:118;;:::o;1801:222::-;1894:4;1932:2;1921:9;1917:18;1909:26;;1945:71;2013:1;2002:9;1998:17;1989:6;1945:71;:::i;:::-;1801:222;;;;:::o;2029:149::-;2065:7;2105:66;2098:5;2094:78;2083:89;;2029:149;;;:::o;2184:120::-;2256:23;2273:5;2256:23;:::i;:::-;2249:5;2246:34;2236:62;;2294:1;2291;2284:12;2236:62;2184:120;:::o;2310:137::-;2355:5;2393:6;2380:20;2371:29;;2409:32;2435:5;2409:32;:::i;:::-;2310:137;;;;:::o;2453:327::-;2511:6;2560:2;2548:9;2539:7;2535:23;2531:32;2528:119;;;2566:79;;:::i;:::-;2528:119;2686:1;2711:52;2755:7;2746:6;2735:9;2731:22;2711:52;:::i;:::-;2701:62;;2657:116;2453:327;;;;:::o;2786:90::-;2820:7;2863:5;2856:13;2849:21;2838:32;;2786:90;;;:::o;2882:109::-;2963:21;2978:5;2963:21;:::i;:::-;2958:3;2951:34;2882:109;;:::o;2997:210::-;3084:4;3122:2;3111:9;3107:18;3099:26;;3135:65;3197:1;3186:9;3182:17;3173:6;3135:65;:::i;:::-;2997:210;;;;:::o;3213:118::-;3300:24;3318:5;3300:24;:::i;:::-;3295:3;3288:37;3213:118;;:::o;3337:222::-;3430:4;3468:2;3457:9;3453:18;3445:26;;3481:71;3549:1;3538:9;3534:17;3525:6;3481:71;:::i;:::-;3337:222;;;;:::o;3565:329::-;3624:6;3673:2;3661:9;3652:7;3648:23;3644:32;3641:119;;;3679:79;;:::i;:::-;3641:119;3799:1;3824:53;3869:7;3860:6;3849:9;3845:22;3824:53;:::i;:::-;3814:63;;3770:117;3565:329;;;;:::o;3900:99::-;3952:6;3986:5;3980:12;3970:22;;3900:99;;;:::o;4005:169::-;4089:11;4123:6;4118:3;4111:19;4163:4;4158:3;4154:14;4139:29;;4005:169;;;;:::o;4180:246::-;4261:1;4271:113;4285:6;4282:1;4279:13;4271:113;;;4370:1;4365:3;4361:11;4355:18;4351:1;4346:3;4342:11;4335:39;4307:2;4304:1;4300:10;4295:15;;4271:113;;;4418:1;4409:6;4404:3;4400:16;4393:27;4242:184;4180:246;;;:::o;4432:102::-;4473:6;4524:2;4520:7;4515:2;4508:5;4504:14;4500:28;4490:38;;4432:102;;;:::o;4540:377::-;4628:3;4656:39;4689:5;4656:39;:::i;:::-;4711:71;4775:6;4770:3;4711:71;:::i;:::-;4704:78;;4791:65;4849:6;4844:3;4837:4;4830:5;4826:16;4791:65;:::i;:::-;4881:29;4903:6;4881:29;:::i;:::-;4876:3;4872:39;4865:46;;4632:285;4540:377;;;;:::o;4923:313::-;5036:4;5074:2;5063:9;5059:18;5051:26;;5123:9;5117:4;5113:20;5109:1;5098:9;5094:17;5087:47;5151:78;5224:4;5215:6;5151:78;:::i;:::-;5143:86;;4923:313;;;;:::o;5242:86::-;5277:7;5317:4;5310:5;5306:16;5295:27;;5242:86;;;:::o;5334:112::-;5417:22;5433:5;5417:22;:::i;:::-;5412:3;5405:35;5334:112;;:::o;5452:324::-;5569:4;5607:2;5596:9;5592:18;5584:26;;5620:71;5688:1;5677:9;5673:17;5664:6;5620:71;:::i;:::-;5701:68;5765:2;5754:9;5750:18;5741:6;5701:68;:::i;:::-;5452:324;;;;;:::o;5782:474::-;5850:6;5858;5907:2;5895:9;5886:7;5882:23;5878:32;5875:119;;;5913:79;;:::i;:::-;5875:119;6033:1;6058:53;6103:7;6094:6;6083:9;6079:22;6058:53;:::i;:::-;6048:63;;6004:117;6160:2;6186:53;6231:7;6222:6;6211:9;6207:22;6186:53;:::i;:::-;6176:63;;6131:118;5782:474;;;;;:::o;6262:332::-;6383:4;6421:2;6410:9;6406:18;6398:26;;6434:71;6502:1;6491:9;6487:17;6478:6;6434:71;:::i;:::-;6515:72;6583:2;6572:9;6568:18;6559:6;6515:72;:::i;:::-;6262:332;;;;;:::o;6600:117::-;6709:1;6706;6699:12;6723:180;6771:77;6768:1;6761:88;6868:4;6865:1;6858:15;6892:4;6889:1;6882:15;6909:281;6992:27;7014:4;6992:27;:::i;:::-;6984:6;6980:40;7122:6;7110:10;7107:22;7086:18;7074:10;7071:34;7068:62;7065:88;;;7133:18;;:::i;:::-;7065:88;7173:10;7169:2;7162:22;6952:238;6909:281;;:::o;7196:129::-;7230:6;7257:20;;:::i;:::-;7247:30;;7286:33;7314:4;7306:6;7286:33;:::i;:::-;7196:129;;;:::o;7331:311::-;7408:4;7498:18;7490:6;7487:30;7484:56;;;7520:18;;:::i;:::-;7484:56;7570:4;7562:6;7558:17;7550:25;;7630:4;7624;7620:15;7612:23;;7331:311;;;:::o;7648:117::-;7757:1;7754;7747:12;7788:710;7884:5;7909:81;7925:64;7982:6;7925:64;:::i;:::-;7909:81;:::i;:::-;7900:90;;8010:5;8039:6;8032:5;8025:21;8073:4;8066:5;8062:16;8055:23;;8126:4;8118:6;8114:17;8106:6;8102:30;8155:3;8147:6;8144:15;8141:122;;;8174:79;;:::i;:::-;8141:122;8289:6;8272:220;8306:6;8301:3;8298:15;8272:220;;;8381:3;8410:37;8443:3;8431:10;8410:37;:::i;:::-;8405:3;8398:50;8477:4;8472:3;8468:14;8461:21;;8348:144;8332:4;8327:3;8323:14;8316:21;;8272:220;;;8276:21;7890:608;;7788:710;;;;;:::o;8521:370::-;8592:5;8641:3;8634:4;8626:6;8622:17;8618:27;8608:122;;8649:79;;:::i;:::-;8608:122;8766:6;8753:20;8791:94;8881:3;8873:6;8866:4;8858:6;8854:17;8791:94;:::i;:::-;8782:103;;8598:293;8521:370;;;;:::o;8897:117::-;9006:1;9003;8996:12;9020:307;9081:4;9171:18;9163:6;9160:30;9157:56;;;9193:18;;:::i;:::-;9157:56;9231:29;9253:6;9231:29;:::i;:::-;9223:37;;9315:4;9309;9305:15;9297:23;;9020:307;;;:::o;9333:146::-;9430:6;9425:3;9420;9407:30;9471:1;9462:6;9457:3;9453:16;9446:27;9333:146;;;:::o;9485:423::-;9562:5;9587:65;9603:48;9644:6;9603:48;:::i;:::-;9587:65;:::i;:::-;9578:74;;9675:6;9668:5;9661:21;9713:4;9706:5;9702:16;9751:3;9742:6;9737:3;9733:16;9730:25;9727:112;;;9758:79;;:::i;:::-;9727:112;9848:54;9895:6;9890:3;9885;9848:54;:::i;:::-;9568:340;9485:423;;;;;:::o;9927:338::-;9982:5;10031:3;10024:4;10016:6;10012:17;10008:27;9998:122;;10039:79;;:::i;:::-;9998:122;10156:6;10143:20;10181:78;10255:3;10247:6;10240:4;10232:6;10228:17;10181:78;:::i;:::-;10172:87;;9988:277;9927:338;;;;:::o;10271:1509::-;10425:6;10433;10441;10449;10457;10506:3;10494:9;10485:7;10481:23;10477:33;10474:120;;;10513:79;;:::i;:::-;10474:120;10633:1;10658:53;10703:7;10694:6;10683:9;10679:22;10658:53;:::i;:::-;10648:63;;10604:117;10760:2;10786:53;10831:7;10822:6;10811:9;10807:22;10786:53;:::i;:::-;10776:63;;10731:118;10916:2;10905:9;10901:18;10888:32;10947:18;10939:6;10936:30;10933:117;;;10969:79;;:::i;:::-;10933:117;11074:78;11144:7;11135:6;11124:9;11120:22;11074:78;:::i;:::-;11064:88;;10859:303;11229:2;11218:9;11214:18;11201:32;11260:18;11252:6;11249:30;11246:117;;;11282:79;;:::i;:::-;11246:117;11387:78;11457:7;11448:6;11437:9;11433:22;11387:78;:::i;:::-;11377:88;;11172:303;11542:3;11531:9;11527:19;11514:33;11574:18;11566:6;11563:30;11560:117;;;11596:79;;:::i;:::-;11560:117;11701:62;11755:7;11746:6;11735:9;11731:22;11701:62;:::i;:::-;11691:72;;11485:288;10271:1509;;;;;;;;:::o;11786:311::-;11863:4;11953:18;11945:6;11942:30;11939:56;;;11975:18;;:::i;:::-;11939:56;12025:4;12017:6;12013:17;12005:25;;12085:4;12079;12075:15;12067:23;;11786:311;;;:::o;12120:710::-;12216:5;12241:81;12257:64;12314:6;12257:64;:::i;:::-;12241:81;:::i;:::-;12232:90;;12342:5;12371:6;12364:5;12357:21;12405:4;12398:5;12394:16;12387:23;;12458:4;12450:6;12446:17;12438:6;12434:30;12487:3;12479:6;12476:15;12473:122;;;12506:79;;:::i;:::-;12473:122;12621:6;12604:220;12638:6;12633:3;12630:15;12604:220;;;12713:3;12742:37;12775:3;12763:10;12742:37;:::i;:::-;12737:3;12730:50;12809:4;12804:3;12800:14;12793:21;;12680:144;12664:4;12659:3;12655:14;12648:21;;12604:220;;;12608:21;12222:608;;12120:710;;;;;:::o;12853:370::-;12924:5;12973:3;12966:4;12958:6;12954:17;12950:27;12940:122;;12981:79;;:::i;:::-;12940:122;13098:6;13085:20;13123:94;13213:3;13205:6;13198:4;13190:6;13186:17;13123:94;:::i;:::-;13114:103;;12930:293;12853:370;;;;:::o;13229:894::-;13347:6;13355;13404:2;13392:9;13383:7;13379:23;13375:32;13372:119;;;13410:79;;:::i;:::-;13372:119;13558:1;13547:9;13543:17;13530:31;13588:18;13580:6;13577:30;13574:117;;;13610:79;;:::i;:::-;13574:117;13715:78;13785:7;13776:6;13765:9;13761:22;13715:78;:::i;:::-;13705:88;;13501:302;13870:2;13859:9;13855:18;13842:32;13901:18;13893:6;13890:30;13887:117;;;13923:79;;:::i;:::-;13887:117;14028:78;14098:7;14089:6;14078:9;14074:22;14028:78;:::i;:::-;14018:88;;13813:303;13229:894;;;;;:::o;14129:114::-;14196:6;14230:5;14224:12;14214:22;;14129:114;;;:::o;14249:184::-;14348:11;14382:6;14377:3;14370:19;14422:4;14417:3;14413:14;14398:29;;14249:184;;;;:::o;14439:132::-;14506:4;14529:3;14521:11;;14559:4;14554:3;14550:14;14542:22;;14439:132;;;:::o;14577:108::-;14654:24;14672:5;14654:24;:::i;:::-;14649:3;14642:37;14577:108;;:::o;14691:179::-;14760:10;14781:46;14823:3;14815:6;14781:46;:::i;:::-;14859:4;14854:3;14850:14;14836:28;;14691:179;;;;:::o;14876:113::-;14946:4;14978;14973:3;14969:14;14961:22;;14876:113;;;:::o;15025:732::-;15144:3;15173:54;15221:5;15173:54;:::i;:::-;15243:86;15322:6;15317:3;15243:86;:::i;:::-;15236:93;;15353:56;15403:5;15353:56;:::i;:::-;15432:7;15463:1;15448:284;15473:6;15470:1;15467:13;15448:284;;;15549:6;15543:13;15576:63;15635:3;15620:13;15576:63;:::i;:::-;15569:70;;15662:60;15715:6;15662:60;:::i;:::-;15652:70;;15508:224;15495:1;15492;15488:9;15483:14;;15448:284;;;15452:14;15748:3;15741:10;;15149:608;;;15025:732;;;;:::o;15763:373::-;15906:4;15944:2;15933:9;15929:18;15921:26;;15993:9;15987:4;15983:20;15979:1;15968:9;15964:17;15957:47;16021:108;16124:4;16115:6;16021:108;:::i;:::-;16013:116;;15763:373;;;;:::o;16142:117::-;16251:1;16248;16241:12;16282:568;16355:8;16365:6;16415:3;16408:4;16400:6;16396:17;16392:27;16382:122;;16423:79;;:::i;:::-;16382:122;16536:6;16523:20;16513:30;;16566:18;16558:6;16555:30;16552:117;;;16588:79;;:::i;:::-;16552:117;16702:4;16694:6;16690:17;16678:29;;16756:3;16748:4;16740:6;16736:17;16726:8;16722:32;16719:41;16716:128;;;16763:79;;:::i;:::-;16716:128;16282:568;;;;;:::o;16856:1079::-;16987:6;16995;17003;17011;17019;17068:2;17056:9;17047:7;17043:23;17039:32;17036:119;;;17074:79;;:::i;:::-;17036:119;17222:1;17211:9;17207:17;17194:31;17252:18;17244:6;17241:30;17238:117;;;17274:79;;:::i;:::-;17238:117;17387:80;17459:7;17450:6;17439:9;17435:22;17387:80;:::i;:::-;17369:98;;;;17165:312;17544:2;17533:9;17529:18;17516:32;17575:18;17567:6;17564:30;17561:117;;;17597:79;;:::i;:::-;17561:117;17710:80;17782:7;17773:6;17762:9;17758:22;17710:80;:::i;:::-;17692:98;;;;17487:313;17839:2;17865:53;17910:7;17901:6;17890:9;17886:22;17865:53;:::i;:::-;17855:63;;17810:118;16856:1079;;;;;;;;:::o;17941:329::-;18000:6;18049:2;18037:9;18028:7;18024:23;18020:32;18017:119;;;18055:79;;:::i;:::-;18017:119;18175:1;18200:53;18245:7;18236:6;18225:9;18221:22;18200:53;:::i;:::-;18190:63;;18146:117;17941:329;;;;:::o;18276:116::-;18346:21;18361:5;18346:21;:::i;:::-;18339:5;18336:32;18326:60;;18382:1;18379;18372:12;18326:60;18276:116;:::o;18398:133::-;18441:5;18479:6;18466:20;18457:29;;18495:30;18519:5;18495:30;:::i;:::-;18398:133;;;;:::o;18537:468::-;18602:6;18610;18659:2;18647:9;18638:7;18634:23;18630:32;18627:119;;;18665:79;;:::i;:::-;18627:119;18785:1;18810:53;18855:7;18846:6;18835:9;18831:22;18810:53;:::i;:::-;18800:63;;18756:117;18912:2;18938:50;18980:7;18971:6;18960:9;18956:22;18938:50;:::i;:::-;18928:60;;18883:115;18537:468;;;;;:::o;19025:553::-;19083:8;19093:6;19143:3;19136:4;19128:6;19124:17;19120:27;19110:122;;19151:79;;:::i;:::-;19110:122;19264:6;19251:20;19241:30;;19294:18;19286:6;19283:30;19280:117;;;19316:79;;:::i;:::-;19280:117;19430:4;19422:6;19418:17;19406:29;;19484:3;19476:4;19468:6;19464:17;19454:8;19450:32;19447:41;19444:128;;;19491:79;;:::i;:::-;19444:128;19025:553;;;;;:::o;19584:529::-;19655:6;19663;19712:2;19700:9;19691:7;19687:23;19683:32;19680:119;;;19718:79;;:::i;:::-;19680:119;19866:1;19855:9;19851:17;19838:31;19896:18;19888:6;19885:30;19882:117;;;19918:79;;:::i;:::-;19882:117;20031:65;20088:7;20079:6;20068:9;20064:22;20031:65;:::i;:::-;20013:83;;;;19809:297;19584:529;;;;;:::o;20119:619::-;20196:6;20204;20212;20261:2;20249:9;20240:7;20236:23;20232:32;20229:119;;;20267:79;;:::i;:::-;20229:119;20387:1;20412:53;20457:7;20448:6;20437:9;20433:22;20412:53;:::i;:::-;20402:63;;20358:117;20514:2;20540:53;20585:7;20576:6;20565:9;20561:22;20540:53;:::i;:::-;20530:63;;20485:118;20642:2;20668:53;20713:7;20704:6;20693:9;20689:22;20668:53;:::i;:::-;20658:63;;20613:118;20119:619;;;;;:::o;20744:934::-;20866:6;20874;20882;20890;20939:2;20927:9;20918:7;20914:23;20910:32;20907:119;;;20945:79;;:::i;:::-;20907:119;21093:1;21082:9;21078:17;21065:31;21123:18;21115:6;21112:30;21109:117;;;21145:79;;:::i;:::-;21109:117;21258:80;21330:7;21321:6;21310:9;21306:22;21258:80;:::i;:::-;21240:98;;;;21036:312;21415:2;21404:9;21400:18;21387:32;21446:18;21438:6;21435:30;21432:117;;;21468:79;;:::i;:::-;21432:117;21581:80;21653:7;21644:6;21633:9;21629:22;21581:80;:::i;:::-;21563:98;;;;21358:313;20744:934;;;;;;;:::o;21684:118::-;21755:22;21771:5;21755:22;:::i;:::-;21748:5;21745:33;21735:61;;21792:1;21789;21782:12;21735:61;21684:118;:::o;21808:135::-;21852:5;21890:6;21877:20;21868:29;;21906:31;21931:5;21906:31;:::i;:::-;21808:135;;;;:::o;21949:615::-;22024:6;22032;22040;22089:2;22077:9;22068:7;22064:23;22060:32;22057:119;;;22095:79;;:::i;:::-;22057:119;22215:1;22240:53;22285:7;22276:6;22265:9;22261:22;22240:53;:::i;:::-;22230:63;;22186:117;22342:2;22368:53;22413:7;22404:6;22393:9;22389:22;22368:53;:::i;:::-;22358:63;;22313:118;22470:2;22496:51;22539:7;22530:6;22519:9;22515:22;22496:51;:::i;:::-;22486:61;;22441:116;21949:615;;;;;:::o;22570:474::-;22638:6;22646;22695:2;22683:9;22674:7;22670:23;22666:32;22663:119;;;22701:79;;:::i;:::-;22663:119;22821:1;22846:53;22891:7;22882:6;22871:9;22867:22;22846:53;:::i;:::-;22836:63;;22792:117;22948:2;22974:53;23019:7;23010:6;22999:9;22995:22;22974:53;:::i;:::-;22964:63;;22919:118;22570:474;;;;;:::o;23050:1089::-;23154:6;23162;23170;23178;23186;23235:3;23223:9;23214:7;23210:23;23206:33;23203:120;;;23242:79;;:::i;:::-;23203:120;23362:1;23387:53;23432:7;23423:6;23412:9;23408:22;23387:53;:::i;:::-;23377:63;;23333:117;23489:2;23515:53;23560:7;23551:6;23540:9;23536:22;23515:53;:::i;:::-;23505:63;;23460:118;23617:2;23643:53;23688:7;23679:6;23668:9;23664:22;23643:53;:::i;:::-;23633:63;;23588:118;23745:2;23771:53;23816:7;23807:6;23796:9;23792:22;23771:53;:::i;:::-;23761:63;;23716:118;23901:3;23890:9;23886:19;23873:33;23933:18;23925:6;23922:30;23919:117;;;23955:79;;:::i;:::-;23919:117;24060:62;24114:7;24105:6;24094:9;24090:22;24060:62;:::i;:::-;24050:72;;23844:288;23050:1089;;;;;;;;:::o;24145:180::-;24193:77;24190:1;24183:88;24290:4;24287:1;24280:15;24314:4;24311:1;24304:15;24331:320;24375:6;24412:1;24406:4;24402:12;24392:22;;24459:1;24453:4;24449:12;24480:18;24470:81;;24536:4;24528:6;24524:17;24514:27;;24470:81;24598:2;24590:6;24587:14;24567:18;24564:38;24561:84;;24617:18;;:::i;:::-;24561:84;24382:269;24331:320;;;:::o;24657:148::-;24759:11;24796:3;24781:18;;24657:148;;;;:::o;24811:141::-;24860:4;24883:3;24875:11;;24906:3;24903:1;24896:14;24940:4;24937:1;24927:18;24919:26;;24811:141;;;:::o;24982:874::-;25085:3;25122:5;25116:12;25151:36;25177:9;25151:36;:::i;:::-;25203:89;25285:6;25280:3;25203:89;:::i;:::-;25196:96;;25323:1;25312:9;25308:17;25339:1;25334:166;;;;25514:1;25509:341;;;;25301:549;;25334:166;25418:4;25414:9;25403;25399:25;25394:3;25387:38;25480:6;25473:14;25466:22;25458:6;25454:35;25449:3;25445:45;25438:52;;25334:166;;25509:341;25576:38;25608:5;25576:38;:::i;:::-;25636:1;25650:154;25664:6;25661:1;25658:13;25650:154;;;25738:7;25732:14;25728:1;25723:3;25719:11;25712:35;25788:1;25779:7;25775:15;25764:26;;25686:4;25683:1;25679:12;25674:17;;25650:154;;;25833:6;25828:3;25824:16;25817:23;;25516:334;;25301:549;;25089:767;;24982:874;;;;:::o;25862:390::-;25968:3;25996:39;26029:5;25996:39;:::i;:::-;26051:89;26133:6;26128:3;26051:89;:::i;:::-;26044:96;;26149:65;26207:6;26202:3;26195:4;26188:5;26184:16;26149:65;:::i;:::-;26239:6;26234:3;26230:16;26223:23;;25972:280;25862:390;;;;:::o;26258:151::-;26398:3;26394:1;26386:6;26382:14;26375:27;26258:151;:::o;26415:400::-;26575:3;26596:84;26678:1;26673:3;26596:84;:::i;:::-;26589:91;;26689:93;26778:3;26689:93;:::i;:::-;26807:1;26802:3;26798:11;26791:18;;26415:400;;;:::o;26821:155::-;26961:7;26957:1;26949:6;26945:14;26938:31;26821:155;:::o;26982:400::-;27142:3;27163:84;27245:1;27240:3;27163:84;:::i;:::-;27156:91;;27256:93;27345:3;27256:93;:::i;:::-;27374:1;27369:3;27365:11;27358:18;;26982:400;;;:::o;27388:1121::-;27815:3;27837:92;27925:3;27916:6;27837:92;:::i;:::-;27830:99;;27946:95;28037:3;28028:6;27946:95;:::i;:::-;27939:102;;28058:148;28202:3;28058:148;:::i;:::-;28051:155;;28223:95;28314:3;28305:6;28223:95;:::i;:::-;28216:102;;28335:148;28479:3;28335:148;:::i;:::-;28328:155;;28500:3;28493:10;;27388:1121;;;;;;:::o;28515:180::-;28563:77;28560:1;28553:88;28660:4;28657:1;28650:15;28684:4;28681:1;28674:15;28701:194;28741:4;28761:20;28779:1;28761:20;:::i;:::-;28756:25;;28795:20;28813:1;28795:20;:::i;:::-;28790:25;;28839:1;28836;28832:9;28824:17;;28863:1;28857:4;28854:11;28851:37;;;28868:18;;:::i;:::-;28851:37;28701:194;;;;:::o;28901:180::-;28949:77;28946:1;28939:88;29046:4;29043:1;29036:15;29070:4;29067:1;29060:15;29087:101;29123:7;29163:18;29156:5;29152:30;29141:41;;29087:101;;;:::o;29194:183::-;29232:3;29255:23;29272:5;29255:23;:::i;:::-;29246:32;;29300:18;29293:5;29290:29;29287:55;;29322:18;;:::i;:::-;29287:55;29369:1;29362:5;29358:13;29351:20;;29194:183;;;:::o;29383:205::-;29422:3;29441:19;29458:1;29441:19;:::i;:::-;29436:24;;29474:19;29491:1;29474:19;:::i;:::-;29469:24;;29516:1;29513;29509:9;29502:16;;29539:18;29534:3;29531:27;29528:53;;;29561:18;;:::i;:::-;29528:53;29383:205;;;;:::o;29594:191::-;29634:3;29653:20;29671:1;29653:20;:::i;:::-;29648:25;;29687:20;29705:1;29687:20;:::i;:::-;29682:25;;29730:1;29727;29723:9;29716:16;;29751:3;29748:1;29745:10;29742:36;;;29758:18;;:::i;:::-;29742:36;29594:191;;;;:::o;29791:332::-;29912:4;29950:2;29939:9;29935:18;29927:26;;29963:71;30031:1;30020:9;30016:17;30007:6;29963:71;:::i;:::-;30044:72;30112:2;30101:9;30097:18;30088:6;30044:72;:::i;:::-;29791:332;;;;;:::o;30129:::-;30250:4;30288:2;30277:9;30273:18;30265:26;;30301:71;30369:1;30358:9;30354:17;30345:6;30301:71;:::i;:::-;30382:72;30450:2;30439:9;30435:18;30426:6;30382:72;:::i;:::-;30129:332;;;;;:::o;30467:233::-;30506:3;30529:24;30547:5;30529:24;:::i;:::-;30520:33;;30575:66;30568:5;30565:77;30562:103;;30645:18;;:::i;:::-;30562:103;30692:1;30685:5;30681:13;30674:20;;30467:233;;;:::o;30706:163::-;30823:11;30860:3;30845:18;;30706:163;;;;:::o;30875:117::-;30984:1;30981;30974:12;30998:98;31082:6;31077:3;31072;31059:30;30998:98;;;:::o;31132:573::-;31278:3;31299:104;31396:6;31391:3;31299:104;:::i;:::-;31292:111;;31427:66;31419:6;31416:78;31413:165;;;31497:79;;:::i;:::-;31413:165;31609:4;31601:6;31597:17;31587:27;;31624:43;31660:6;31655:3;31648:5;31624:43;:::i;:::-;31692:6;31687:3;31683:16;31676:23;;31132:573;;;;;:::o;31711:355::-;31883:3;31905:135;32036:3;32027:6;32019;31905:135;:::i;:::-;31898:142;;32057:3;32050:10;;31711:355;;;;;:::o;32096:330::-;32212:3;32233:89;32315:6;32310:3;32233:89;:::i;:::-;32226:96;;32332:56;32381:6;32376:3;32369:5;32332:56;:::i;:::-;32413:6;32408:3;32404:16;32397:23;;32096:330;;;;;:::o;32432:295::-;32574:3;32596:105;32697:3;32688:6;32680;32596:105;:::i;:::-;32589:112;;32718:3;32711:10;;32432:295;;;;;:::o;32733:269::-;32862:3;32884:92;32972:3;32963:6;32884:92;:::i;:::-;32877:99;;32993:3;32986:10;;32733:269;;;;:::o;33008:97::-;33067:6;33095:3;33085:13;;33008:97;;;;:::o;33111:93::-;33148:6;33195:2;33190;33183:5;33179:14;33175:23;33165:33;;33111:93;;;:::o;33210:107::-;33254:8;33304:5;33298:4;33294:16;33273:37;;33210:107;;;;:::o;33323:393::-;33392:6;33442:1;33430:10;33426:18;33465:97;33495:66;33484:9;33465:97;:::i;:::-;33583:39;33613:8;33602:9;33583:39;:::i;:::-;33571:51;;33655:4;33651:9;33644:5;33640:21;33631:30;;33704:4;33694:8;33690:19;33683:5;33680:30;33670:40;;33399:317;;33323:393;;;;;:::o;33722:60::-;33750:3;33771:5;33764:12;;33722:60;;;:::o;33788:142::-;33838:9;33871:53;33889:34;33898:24;33916:5;33898:24;:::i;:::-;33889:34;:::i;:::-;33871:53;:::i;:::-;33858:66;;33788:142;;;:::o;33936:75::-;33979:3;34000:5;33993:12;;33936:75;;;:::o;34017:269::-;34127:39;34158:7;34127:39;:::i;:::-;34188:91;34237:41;34261:16;34237:41;:::i;:::-;34229:6;34222:4;34216:11;34188:91;:::i;:::-;34182:4;34175:105;34093:193;34017:269;;;:::o;34292:73::-;34337:3;34292:73;:::o;34371:189::-;34448:32;;:::i;:::-;34489:65;34547:6;34539;34533:4;34489:65;:::i;:::-;34424:136;34371:189;;:::o;34566:186::-;34626:120;34643:3;34636:5;34633:14;34626:120;;;34697:39;34734:1;34727:5;34697:39;:::i;:::-;34670:1;34663:5;34659:13;34650:22;;34626:120;;;34566:186;;:::o;34758:543::-;34859:2;34854:3;34851:11;34848:446;;;34893:38;34925:5;34893:38;:::i;:::-;34977:29;34995:10;34977:29;:::i;:::-;34967:8;34963:44;35160:2;35148:10;35145:18;35142:49;;;35181:8;35166:23;;35142:49;35204:80;35260:22;35278:3;35260:22;:::i;:::-;35250:8;35246:37;35233:11;35204:80;:::i;:::-;34863:431;;34848:446;34758:543;;;:::o;35307:117::-;35361:8;35411:5;35405:4;35401:16;35380:37;;35307:117;;;;:::o;35430:169::-;35474:6;35507:51;35555:1;35551:6;35543:5;35540:1;35536:13;35507:51;:::i;:::-;35503:56;35588:4;35582;35578:15;35568:25;;35481:118;35430:169;;;;:::o;35604:295::-;35680:4;35826:29;35851:3;35845:4;35826:29;:::i;:::-;35818:37;;35888:3;35885:1;35881:11;35875:4;35872:21;35864:29;;35604:295;;;;:::o;35904:1403::-;36028:44;36068:3;36063;36028:44;:::i;:::-;36137:18;36129:6;36126:30;36123:56;;;36159:18;;:::i;:::-;36123:56;36203:38;36235:4;36229:11;36203:38;:::i;:::-;36288:67;36348:6;36340;36334:4;36288:67;:::i;:::-;36382:1;36411:2;36403:6;36400:14;36428:1;36423:632;;;;37099:1;37116:6;37113:84;;;37172:9;37167:3;37163:19;37150:33;37141:42;;37113:84;37223:67;37283:6;37276:5;37223:67;:::i;:::-;37217:4;37210:81;37072:229;36393:908;;36423:632;36475:4;36471:9;36463:6;36459:22;36509:37;36541:4;36509:37;:::i;:::-;36568:1;36582:215;36596:7;36593:1;36590:14;36582:215;;;36682:9;36677:3;36673:19;36660:33;36652:6;36645:49;36733:1;36725:6;36721:14;36711:24;;36780:2;36769:9;36765:18;36752:31;;36619:4;36616:1;36612:12;36607:17;;36582:215;;;36825:6;36816:7;36813:19;36810:186;;;36890:9;36885:3;36881:19;36868:33;36933:48;36975:4;36967:6;36963:17;36952:9;36933:48;:::i;:::-;36925:6;36918:64;36833:163;36810:186;37042:1;37038;37030:6;37026:14;37022:22;37016:4;37009:36;36430:625;;;36393:908;;36003:1304;;;35904:1403;;;:::o;37313:180::-;37361:77;37358:1;37351:88;37458:4;37455:1;37448:15;37482:4;37479:1;37472:15;37499:410;37539:7;37562:20;37580:1;37562:20;:::i;:::-;37557:25;;37596:20;37614:1;37596:20;:::i;:::-;37591:25;;37651:1;37648;37644:9;37673:30;37691:11;37673:30;:::i;:::-;37662:41;;37852:1;37843:7;37839:15;37836:1;37833:22;37813:1;37806:9;37786:83;37763:139;;37882:18;;:::i;:::-;37763:139;37547:362;37499:410;;;;:::o;37915:171::-;37954:3;37977:24;37995:5;37977:24;:::i;:::-;37968:33;;38023:4;38016:5;38013:15;38010:41;;38031:18;;:::i;:::-;38010:41;38078:1;38071:5;38067:13;38060:20;;37915:171;;;:::o;38092:98::-;38143:6;38177:5;38171:12;38161:22;;38092:98;;;:::o;38196:168::-;38279:11;38313:6;38308:3;38301:19;38353:4;38348:3;38344:14;38329:29;;38196:168;;;;:::o;38370:373::-;38456:3;38484:38;38516:5;38484:38;:::i;:::-;38538:70;38601:6;38596:3;38538:70;:::i;:::-;38531:77;;38617:65;38675:6;38670:3;38663:4;38656:5;38652:16;38617:65;:::i;:::-;38707:29;38729:6;38707:29;:::i;:::-;38702:3;38698:39;38691:46;;38460:283;38370:373;;;;:::o;38749:751::-;38972:4;39010:3;38999:9;38995:19;38987:27;;39024:71;39092:1;39081:9;39077:17;39068:6;39024:71;:::i;:::-;39105:72;39173:2;39162:9;39158:18;39149:6;39105:72;:::i;:::-;39187;39255:2;39244:9;39240:18;39231:6;39187:72;:::i;:::-;39269;39337:2;39326:9;39322:18;39313:6;39269:72;:::i;:::-;39389:9;39383:4;39379:20;39373:3;39362:9;39358:19;39351:49;39417:76;39488:4;39479:6;39417:76;:::i;:::-;39409:84;;38749:751;;;;;;;;:::o;39506:141::-;39562:5;39593:6;39587:13;39578:22;;39609:32;39635:5;39609:32;:::i;:::-;39506:141;;;;:::o;39653:349::-;39722:6;39771:2;39759:9;39750:7;39746:23;39742:32;39739:119;;;39777:79;;:::i;:::-;39739:119;39897:1;39922:63;39977:7;39968:6;39957:9;39953:22;39922:63;:::i;:::-;39912:73;;39868:127;39653:349;;;;:::o;40008:1053::-;40331:4;40369:3;40358:9;40354:19;40346:27;;40383:71;40451:1;40440:9;40436:17;40427:6;40383:71;:::i;:::-;40464:72;40532:2;40521:9;40517:18;40508:6;40464:72;:::i;:::-;40583:9;40577:4;40573:20;40568:2;40557:9;40553:18;40546:48;40611:108;40714:4;40705:6;40611:108;:::i;:::-;40603:116;;40766:9;40760:4;40756:20;40751:2;40740:9;40736:18;40729:48;40794:108;40897:4;40888:6;40794:108;:::i;:::-;40786:116;;40950:9;40944:4;40940:20;40934:3;40923:9;40919:19;40912:49;40978:76;41049:4;41040:6;40978:76;:::i;:::-;40970:84;;40008:1053;;;;;;;;:::o;41067:553::-;41244:4;41282:3;41271:9;41267:19;41259:27;;41296:71;41364:1;41353:9;41349:17;41340:6;41296:71;:::i;:::-;41377:72;41445:2;41434:9;41430:18;41421:6;41377:72;:::i;:::-;41459;41527:2;41516:9;41512:18;41503:6;41459:72;:::i;:::-;41541;41609:2;41598:9;41594:18;41585:6;41541:72;:::i;:::-;41067:553;;;;;;;:::o;41626:634::-;41847:4;41885:2;41874:9;41870:18;41862:26;;41934:9;41928:4;41924:20;41920:1;41909:9;41905:17;41898:47;41962:108;42065:4;42056:6;41962:108;:::i;:::-;41954:116;;42117:9;42111:4;42107:20;42102:2;42091:9;42087:18;42080:48;42145:108;42248:4;42239:6;42145:108;:::i;:::-;42137:116;;41626:634;;;;;:::o
Swarm Source
ipfs://4663c8f2a003d356b3ae3c524b082d5ed7e152a008b25704ce6ceb0b7942b614
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.