More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 474 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 21035326 | 11 days ago | IN | 0 ETH | 0.00070644 | ||||
Withdraw ERC20 | 21034392 | 12 days ago | IN | 0 ETH | 0.00047554 | ||||
Approve | 20901738 | 30 days ago | IN | 0 ETH | 0.00020906 | ||||
Approve | 20901545 | 30 days ago | IN | 0 ETH | 0.00031337 | ||||
Approve | 20893339 | 31 days ago | IN | 0 ETH | 0.00075933 | ||||
Approve | 20875980 | 34 days ago | IN | 0 ETH | 0.0002858 | ||||
Approve | 20543907 | 80 days ago | IN | 0 ETH | 0.00004629 | ||||
Approve | 20383323 | 102 days ago | IN | 0 ETH | 0.00010406 | ||||
Approve | 20316888 | 112 days ago | IN | 0 ETH | 0.00032027 | ||||
Approve | 20212652 | 126 days ago | IN | 0 ETH | 0.00057739 | ||||
Approve | 20137337 | 137 days ago | IN | 0 ETH | 0.00019506 | ||||
Transfer | 20103736 | 141 days ago | IN | 0 ETH | 0.00015028 | ||||
Approve | 20073890 | 146 days ago | IN | 0 ETH | 0.00015415 | ||||
Approve | 20073807 | 146 days ago | IN | 0 ETH | 0.00015093 | ||||
Approve | 20049780 | 149 days ago | IN | 0 ETH | 0.00041148 | ||||
Approve | 20034026 | 151 days ago | IN | 0 ETH | 0.00117397 | ||||
Approve | 20009925 | 155 days ago | IN | 0 ETH | 0.00046842 | ||||
Approve | 19965374 | 161 days ago | IN | 0 ETH | 0.00027001 | ||||
Approve | 19865473 | 175 days ago | IN | 0 ETH | 0.00037243 | ||||
Approve | 19862686 | 175 days ago | IN | 0 ETH | 0.00134112 | ||||
Approve | 19862677 | 175 days ago | IN | 0 ETH | 0.00088863 | ||||
Transfer | 19854279 | 176 days ago | IN | 0 ETH | 0.00014602 | ||||
Transfer | 19848430 | 177 days ago | IN | 0 ETH | 0.00019528 | ||||
Approve | 19797943 | 184 days ago | IN | 0 ETH | 0.00034485 | ||||
Approve | 19709930 | 197 days ago | IN | 0 ETH | 0.00040654 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HERCoin
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-12-05 */ // SPDX-License-Identifier: UNLICENSED // File: PoolAddress.sol pragma solidity >=0.5.0; /// @title Provides functions for deriving a pool address from the factory, tokens, and the fee library PoolAddress { bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; /// @notice The identifying key of the pool struct PoolKey { address token0; address token1; uint24 fee; } /// @notice Returns PoolKey: the ordered tokens with the matched fee levels /// @param tokenA The first token of a pool, unsorted /// @param tokenB The second token of a pool, unsorted /// @param fee The fee level of the pool /// @return Poolkey The pool details with ordered token0 and token1 assignments function getPoolKey(address tokenA, address tokenB, uint24 fee) internal pure returns (PoolKey memory) { if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); return PoolKey({token0: tokenA, token1: tokenB, fee: fee}); } /// @notice Deterministically computes the pool address given the factory and PoolKey /// @param factory The Uniswap V3 factory contract address /// @param key The PoolKey /// @return pool The contract address of the V3 pool function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) { require(key.token0 < key.token1); pool = address( uint160( uint256( keccak256( abi.encodePacked( hex"ff", factory, keccak256(abi.encode(key.token0, key.token1, key.fee)), POOL_INIT_CODE_HASH ) ) ) ) ); } } // File: @openzeppelin/contracts/utils/Nonces.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol) pragma solidity ^0.8.20; /** * @dev Provides tracking nonces for addresses. Nonces will only increment. */ abstract contract Nonces { /** * @dev The nonce used for an `account` is not the expected current nonce. */ error InvalidAccountNonce(address account, uint256 currentNonce); mapping(address account => uint256) private _nonces; /** * @dev Returns the next unused nonce for an address. */ function nonces(address owner) public view virtual returns (uint256) { return _nonces[owner]; } /** * @dev Consumes a nonce. * * Returns the current value and increments nonce. */ function _useNonce(address owner) internal virtual returns (uint256) { // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be // decremented or reset. This guarantees that the nonce never overflows. unchecked { // It is important to do x++ and not ++x here. return _nonces[owner]++; } } /** * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`. */ function _useCheckedNonce(address owner, uint256 nonce) internal virtual { uint256 current = _useNonce(owner); if (nonce != current) { revert InvalidAccountNonce(owner, current); } } } // File: @openzeppelin/contracts/interfaces/IERC5267.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); } // File: @openzeppelin/contracts/utils/StorageSlot.sol // 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 } } } // File: @openzeppelin/contracts/utils/ShortStrings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using * {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } } // File: @openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol // 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) } } } // File: @openzeppelin/contracts/utils/cryptography/EIP712.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * @custom:oz-upgrades-unsafe-allow state-variable-immutable */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: By default this function reads _name which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { return _name.toStringWithFallback(_nameFallback); } /** * @dev The version parameter for the EIP712 domain. * * NOTE: By default this function reads _version which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { return _version.toStringWithFallback(_versionFallback); } } // File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol // 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); } } } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.0) (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; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } } // File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces { bytes32 private constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /** * @dev Permit deadline has expired. */ error ERC2612ExpiredSignature(uint256 deadline); /** * @dev Mismatched signature. */ error ERC2612InvalidSigner(address signer, address owner); /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ constructor(string memory name) EIP712(name, "1") {} /** * @inheritdoc IERC20Permit */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { if (block.timestamp > deadline) { revert ERC2612ExpiredSignature(deadline); } bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); if (signer != owner) { revert ERC2612InvalidSigner(signer, owner); } _approve(owner, spender, value); } /** * @inheritdoc IERC20Permit */ function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) { return super.nonces(owner); } /** * @inheritdoc IERC20Permit */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view virtual returns (bytes32) { return _domainSeparatorV4(); } } // File: HerCoin.sol pragma solidity ^0.8.20; interface IUniswapRouterV2 { function WETH() external pure returns (address); } address constant UNISWAP_V2_ROUTER = address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); address constant UNISWAP_V2_FACTORY = address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f); address constant UNISWAP_V3_FACTORY = address(0x1F98431c8aD98523631AE4a59f267346ea31F984); contract HERCoin is ERC20, ERC20Permit, Ownable { //------------------------------------------------------------------------------------// // errors // //------------------------------------------------------------------------------------// error MaxHoldingAmountExceeded(); error ErrNotTokenRedeemer(); error ErrTotalSupplyExceeded(); error ErrNotLiquidtyProvider(); error ErrExceedingMaxAmountInSellOrder(); error ErrExceedingMaxAmountInBuyOrder(); error ErrNoSandwhichesHere(); //------------------------------------------------------------------------------------// // constants // //------------------------------------------------------------------------------------// uint256 public constant TOTAL_SUPPLY = 69_420_000 ether; uint256 public constant MAX_HOLDING_AMOUNT_PER_WALLET = TOTAL_SUPPLY * uint256(1) / uint256(100); //3% /// @dev adjust these values as needed uint256 public constant MAX_BUY_ORDER = TOTAL_SUPPLY * uint256(5) / uint256(1000); //3% /// @dev adjust these values as needed uint256 public constant MAX_SELL_ORDER = TOTAL_SUPPLY * uint256(5) / uint256(1000); //3 /// @dev jared from subway address address private constant JARED = address(0xae2Fc483527B8EF99EB5D9B44875F005ba1FaE13); //------------------------------------------------------------------------------------// // immutable // //------------------------------------------------------------------------------------// /** * @notice the primary uniswap(v2) pair for HER */ address public immutable uniswapV2Pair; //------------------------------------------------------------------------------------// // variables // //------------------------------------------------------------------------------------// /** * @notice the timestamp of when trading opens * @dev this is set in the _update override when an LP makes a trade */ uint256 public genesisTimestamp; /** * @notice the address of the token redeemer * @dev */ address public tokenRedeemer = 0x4b2ADfCa850EF1b1a425572F552bb9B35aF63d61; /** * @notice a boolean indicating if sell and buy limits are on * @dev this is set to false when the owner renounces ownership */ bool public limitsOn = false; //------------------------------------------------------------------------------------// // mappings // //------------------------------------------------------------------------------------// /// @notice A mapping of pool addresses to a boolean indicating if the pool is registered /// @dev only univ2 and univ3 her/weth pools are registered mapping(address => AddressData) private _addressData; struct AddressData { bool isPool; bool isExcludedFromTax; } //------------------------------------------------------------------------------------// // constructor // //------------------------------------------------------------------------------------// /** * @notice Constructs the HerToken contract * @param _owner The address to set as owner */ constructor(address _owner) payable ERC20("HER Coin", "HER") ERC20Permit("HER Coin") Ownable(_owner) { address weth = IUniswapRouterV2(UNISWAP_V2_ROUTER).WETH(); uniswapV2Pair = pairFor(UNISWAP_V2_FACTORY, address(this), weth); _addressData[uniswapV2Pair] = AddressData({isPool: true, isExcludedFromTax: false}); _addressData[computeUniv3Address(weth, 500)] = AddressData({isPool: true, isExcludedFromTax: false}); _addressData[computeUniv3Address(weth, 3000)] = AddressData({isPool: true, isExcludedFromTax: false}); _addressData[computeUniv3Address(weth, 10000)] = AddressData({isPool: true, isExcludedFromTax: false}); _addressData[_owner] = AddressData({isPool: false, isExcludedFromTax: true}); _addressData[address(this)] = AddressData({isPool: false, isExcludedFromTax: true}); _addressData[_owner] = AddressData({isPool: false, isExcludedFromTax: true}); } //------------------------------------------------------------------------------------// // ERC20 Overrides // //------------------------------------------------------------------------------------// /** * @dev - overrides ERC20 update for custom logic * @dev the restrictions are as follows: * 1. If the sender is a registered pool, enforce a tax * 2. If the recipient is a registered pool, enforce a tax * 3. If limits are on, enforce a max holding amount per wallet * @param from The address to transfer from * @param to The address to transfer to * @param value The amount to transfer */ function _update(address from, address to, uint256 value) internal override(ERC20) { bool _limitsOn = limitsOn; uint256 _value = value; AddressData memory fromData = _addressData[from]; AddressData memory toData = _addressData[to]; if (from == JARED || to == JARED) { _revert(ErrNoSandwhichesHere.selector); } if (!fromData.isExcludedFromTax && !toData.isExcludedFromTax) { if (fromData.isPool) { if (_limitsOn) { uint256 balanceTo = balanceOf(to); if (balanceTo + value > MAX_HOLDING_AMOUNT_PER_WALLET) { _revert(MaxHoldingAmountExceeded.selector); } if (value > MAX_BUY_ORDER) { _revert(ErrExceedingMaxAmountInBuyOrder.selector); } } uint256 tax = _computeTax(value); _value = value - tax; super._update(from, address(this), tax); } if (toData.isPool) { if (_limitsOn) { if (value > MAX_SELL_ORDER) { _revert(ErrExceedingMaxAmountInSellOrder.selector); } } uint256 tax = _computeTax(value); _value = value - tax; super._update(from, address(this), tax); } } super._update(from, to, _value); } //------------------------------------------------------------------------------------// // Airdrop // //------------------------------------------------------------------------------------// /** * @notice Allows the owner to mint tokens to multiple accounts * @param accounts The accounts to mint to * @param amounts The amounts to mint * @dev reverts if the total supply exceeds TOTAL_SUPPLY */ function airdrop(address accounts, uint256 amounts) external onlyOwner { _mint(accounts, amounts); uint256 newTotalSupply = totalSupply(); if (newTotalSupply > TOTAL_SUPPLY) { _revert(ErrTotalSupplyExceeded.selector); } } //------------------------------------------------------------------------------------// // withdaraw tokens // //------------------------------------------------------------------------------------// /** * @notice allows anyone to sent lost tokens back to the treasury * @param _token The token to withdraw, use address(0) for ETH */ function withdrawERC20(address _token, address to) external { _checkTokenRedeemer(); if (_token == address(0)) { (bool os,) = payable(to).call{value: address(this).balance}(""); require(os, "withdrawERC20: ETH transfer failed"); } else { ERC20(_token).transfer(to, ERC20(_token).balanceOf(address(this))); } } //------------------------------------------------------------------------------------// // access-gated funcs // //------------------------------------------------------------------------------------// /** * @notice Allows the the token redeemer to declare a new token redeemer * @param _tokenRedeemer The new token redeemer */ function setTokenRedeemer(address _tokenRedeemer) external { _checkTokenRedeemer(); address _oldRedeemer = tokenRedeemer; _addressData[_oldRedeemer] = AddressData({isPool: false, isExcludedFromTax: false}); tokenRedeemer = _tokenRedeemer; _addressData[_tokenRedeemer] = AddressData({isPool: false, isExcludedFromTax: true}); } /** * @notice Allows the owner to manually override the address data * @param _address The address to override * @param _isPool A boolean indicating if the address is a pool * @param _isExcludedFromTax A boolean indicating if the address is excluded from tax */ function emergencyOverrideAddressData(address _address, bool _isPool, bool _isExcludedFromTax) external onlyOwner { _addressData[_address] = AddressData({isPool: _isPool, isExcludedFromTax: _isExcludedFromTax}); } /** * @notice Allows the owner to set the limits status * @param _limitsOn A boolean indicating if limits are on */ function setLimitsStatus(bool _limitsOn) external onlyOwner { limitsOn = _limitsOn; } /** * @notice Allows the owner to renounce the contract which removes buy and sell limits * @dev This is irreversible */ function renounceOwnership() public override onlyOwner { limitsOn = false; super.renounceOwnership(); } //------------------------------------------------------------------------------------// // getters // //------------------------------------------------------------------------------------// function addressData(address _address) external view returns (AddressData memory) { return _addressData[_address]; } //------------------------------------------------------------------------------------// // utils // //------------------------------------------------------------------------------------// /** * @dev Sort two tokens deterministically * @param tokenA The first token of a pair * @param tokenB The second token of a pair * @return token0 The token that sorts lower than the other token * @return token1 The token that sorts higher than the other token */ function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); } /** * @dev Compute a pair address from the two tokens * @param factory The Uniswap V2 factory contract address * @param tokenA The first token of a pair * @param tokenB The second token of a pair * @return pair The pair address */ function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); pair = address( uint160( uint256( keccak256( abi.encodePacked( hex"ff", factory, keccak256(abi.encodePacked(token0, token1)), hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash ) ) ) ) ); } /** * @dev Compute tax based on time since launch * @param amount The amount to compute tax for * @dev the breakdown is as follows: * 0-1 minute: 10% * 1-10 minutes: 5% * 10-60 minutes: 3% * 60+ minutes: 2% * @return The amount of tax to pay */ function _computeTax(uint256 amount) internal returns (uint256) { uint256 _genesisTimestamp = genesisTimestamp; if (_genesisTimestamp == 0) { genesisTimestamp = block.timestamp; return (amount * 10) / 100; //10% tax } uint256 secondsSinceLaunch = block.timestamp - _genesisTimestamp; if (secondsSinceLaunch < 60) { //1 minute return (amount * 10) / 100; //10% tax } if (secondsSinceLaunch < 600) { //10 minutes return (amount * 5) / 100; //5% tax } //60 minutes if (secondsSinceLaunch < 3600) { return (amount * 3) / 100; //3% tax } return (amount * 2) / 100; //2% tax } /** * @dev Compute the univ3 pool address given the WETH address and fee level * @param weth The WETH address * @param fee The fee level * @return pool The pool address */ function computeUniv3Address(address weth, uint24 fee) internal view returns (address) { PoolAddress.PoolKey memory key = PoolAddress.getPoolKey(address(this), weth, fee); address pool = PoolAddress.computeAddress(UNISWAP_V3_FACTORY, key); return pool; } /** * @dev Check if the caller is the token redeemer */ function _checkTokenRedeemer() internal view { if (msg.sender != tokenRedeemer) { _revert(ErrNotTokenRedeemer.selector); } } /** * @notice an efficient revert * @param selector The function selector to revert with */ function _revert(bytes4 selector) private pure { assembly { mstore(0x0, selector) revert(0x0, 0x4) } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[],"name":"ErrExceedingMaxAmountInBuyOrder","type":"error"},{"inputs":[],"name":"ErrExceedingMaxAmountInSellOrder","type":"error"},{"inputs":[],"name":"ErrNoSandwhichesHere","type":"error"},{"inputs":[],"name":"ErrNotLiquidtyProvider","type":"error"},{"inputs":[],"name":"ErrNotTokenRedeemer","type":"error"},{"inputs":[],"name":"ErrTotalSupplyExceeded","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"MaxHoldingAmountExceeded","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":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BUY_ORDER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_HOLDING_AMOUNT_PER_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SELL_ORDER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addressData","outputs":[{"components":[{"internalType":"bool","name":"isPool","type":"bool"},{"internalType":"bool","name":"isExcludedFromTax","type":"bool"}],"internalType":"struct HERCoin.AddressData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accounts","type":"address"},{"internalType":"uint256","name":"amounts","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_isPool","type":"bool"},{"internalType":"bool","name":"_isExcludedFromTax","type":"bool"}],"name":"emergencyOverrideAddressData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitsOn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_limitsOn","type":"bool"}],"name":"setLimitsStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenRedeemer","type":"address"}],"name":"setTokenRedeemer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenRedeemer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610180604052734b2adfca850ef1b1a425572f552bb9b35af63d61600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f600a60146101000a81548160ff0219169083151502179055506040516200442438038062004424833981810160405281019062000098919062000d2e565b806040518060400160405280600881526020017f48455220436f696e000000000000000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600881526020017f48455220436f696e0000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f4845520000000000000000000000000000000000000000000000000000000000815250816003908162000183919062000fc2565b50806004908162000195919062000fc2565b505050620001ae6005836200080e60201b90919060201c565b6101208181525050620001cc6006826200080e60201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a081815250506200020b6200086360201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620002bc575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620002b39190620010b7565b60405180910390fd5b620002cd81620008bf60201b60201c565b505f737a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200032d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000353919062000d2e565b90506200037c735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f30836200098260201b60201c565b73ffffffffffffffffffffffffffffffffffffffff166101608173ffffffffffffffffffffffffffffffffffffffff168152505060405180604001604052806001151581526020015f1515815250600b5f6101605173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505060405180604001604052806001151581526020015f1515815250600b5f6200047a846101f4620009fd60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505060405180604001604052806001151581526020015f1515815250600b5f6200052384610bb8620009fd60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505060405180604001604052806001151581526020015f1515815250600b5f620005cc84612710620009fd60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505060405180604001604052805f1515815260200160011515815250600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505060405180604001604052805f1515815260200160011515815250600b5f3073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505060405180604001604052805f1515815260200160011515815250600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055509050505050620014da565b5f60208351101562000833576200082b8362000a4860201b60201c565b90506200085d565b82620008458362000ab260201b60201c565b5f01908162000855919062000fc2565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e051610100514630604051602001620008a4959493929190620010fd565b60405160208183030381529060405280519060200120905090565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f805f62000997858562000abb60201b60201c565b91509150858282604051602001620009b1929190620011a5565b60405160208183030381529060405280519060200120604051602001620009da9291906200129e565b604051602081830303815290604052805190602001205f1c925050509392505050565b5f8062000a1230858562000b0b60201b60201c565b90505f62000a3b731f98431c8ad98523631ae4a59f267346ea31f9848362000baa60201b60201c565b9050809250505092915050565b5f80829050601f8151111562000a9757826040517f305a27a900000000000000000000000000000000000000000000000000000000815260040162000a8e919062001371565b60405180910390fd5b80518162000aa590620013c2565b5f1c175f1b915050919050565b5f819050919050565b5f808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161062000af957828462000afc565b83835b80925081935050509250929050565b62000b1562000c7a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16111562000b5557828480945081955050505b60405180606001604052808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018362ffffff1681525090509392505050565b5f816020015173ffffffffffffffffffffffffffffffffffffffff16825f015173ffffffffffffffffffffffffffffffffffffffff161062000bea575f80fd5b82825f01518360200151846040015160405160200162000c0d9392919062001450565b604051602081830303815290604052805190602001207fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b545f1b60405160200162000c5a939291906200148b565b604051602081830303815290604052805190602001205f1c905092915050565b60405180606001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f62ffffff1681525090565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000cf88262000ccd565b9050919050565b62000d0a8162000cec565b811462000d15575f80fd5b50565b5f8151905062000d288162000cff565b92915050565b5f6020828403121562000d465762000d4562000cc9565b5b5f62000d558482850162000d18565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168062000dda57607f821691505b60208210810362000df05762000def62000d95565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830262000e547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000e17565b62000e60868362000e17565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f62000eaa62000ea462000e9e8462000e78565b62000e81565b62000e78565b9050919050565b5f819050919050565b62000ec58362000e8a565b62000edd62000ed48262000eb1565b84845462000e23565b825550505050565b5f90565b62000ef362000ee5565b62000f0081848462000eba565b505050565b5b8181101562000f275762000f1b5f8262000ee9565b60018101905062000f06565b5050565b601f82111562000f765762000f408162000df6565b62000f4b8462000e08565b8101602085101562000f5b578190505b62000f7362000f6a8562000e08565b83018262000f05565b50505b505050565b5f82821c905092915050565b5f62000f985f198460080262000f7b565b1980831691505092915050565b5f62000fb2838362000f87565b9150826002028217905092915050565b62000fcd8262000d5e565b67ffffffffffffffff81111562000fe95762000fe862000d68565b5b62000ff5825462000dc2565b6200100282828562000f2b565b5f60209050601f83116001811462001038575f841562001023578287015190505b6200102f858262000fa5565b8655506200109e565b601f198416620010488662000df6565b5f5b8281101562001071578489015182556001820191506020850194506020810190506200104a565b868310156200109157848901516200108d601f89168262000f87565b8355505b6001600288020188555050505b505050505050565b620010b18162000cec565b82525050565b5f602082019050620010cc5f830184620010a6565b92915050565b5f819050919050565b620010e681620010d2565b82525050565b620010f78162000e78565b82525050565b5f60a082019050620011125f830188620010db565b620011216020830187620010db565b620011306040830186620010db565b6200113f6060830185620010ec565b6200114e6080830184620010a6565b9695505050505050565b5f8160601b9050919050565b5f620011708262001158565b9050919050565b5f620011838262001164565b9050919050565b6200119f620011998262000cec565b62001177565b82525050565b5f620011b282856200118a565b601482019150620011c482846200118a565b6014820191508190509392505050565b5f81905092915050565b7fff000000000000000000000000000000000000000000000000000000000000005f82015250565b5f62001214600183620011d4565b91506200122182620011de565b600182019050919050565b5f819050919050565b6200124a6200124482620010d2565b6200122c565b82525050565b7f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f5f82015250565b5f62001286602083620011d4565b9150620012938262001250565b602082019050919050565b5f620012aa8262001206565b9150620012b882856200118a565b601482019150620012ca828462001235565b602082019150620012db8262001278565b91508190509392505050565b5f82825260208201905092915050565b5f5b8381101562001316578082015181840152602081019050620012f9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6200133d8262000d5e565b620013498185620012e7565b93506200135b818560208601620012f7565b620013668162001321565b840191505092915050565b5f6020820190508181035f8301526200138b818462001331565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f620013b98251620010d2565b80915050919050565b5f620013ce8262001393565b82620013da846200139d565b9050620013e781620013ac565b925060208210156200142a57620014257fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080262000e17565b831692505b5050919050565b5f62ffffff82169050919050565b6200144a8162001431565b82525050565b5f606082019050620014655f830186620010a6565b620014746020830185620010a6565b6200148360408301846200143f565b949350505050565b5f620014978262001206565b9150620014a582866200118a565b601482019150620014b7828562001235565b602082019150620014c9828462001235565b602082019150819050949350505050565b60805160a05160c05160e05161010051610120516101405161016051612eee620015365f395f6106fe01525f61147e01525f61144301525f611c2f01525f611c0e01525f6112a701525f6112fd01525f6113260152612eee5ff3fe608060405234801561000f575f80fd5b50600436106101d8575f3560e01c80637ecebe0011610102578063a9059cbb116100a0578063dd62ed3e1161006f578063dd62ed3e1461053c578063e56cfceb1461056c578063f2fde38b1461058a578063fcfcd59f146105a6576101d8565b8063a9059cbb146104b6578063ac238956146104e6578063cacf66ab14610502578063d505accf14610520576101d8565b80638da5cb5b116100dc5780638da5cb5b14610440578063902d55a51461045e5780639456fbcc1461047c57806395d89b4114610498576101d8565b80637ecebe00146103d057806384b0196e146104005780638ba4cc3c14610424576101d8565b80633644e5151161017a578063699df72611610149578063699df7261461035c57806370a082311461037a578063715018a6146103aa578063797de370146103b4576101d8565b80633644e515146102d257806349bd5a5e146102f05780635fb5fe3b1461030e578063650a92cb1461033e576101d8565b80631c42047a116101b65780631c42047a1461024857806323b872dd146102665780632492722614610296578063313ce567146102b4576101d8565b806306fdde03146101dc578063095ea7b3146101fa57806318160ddd1461022a575b5f80fd5b6101e46105c2565b6040516101f1919061241f565b60405180910390f35b610214600480360381019061020f91906124d0565b610652565b6040516102219190612528565b60405180910390f35b610232610674565b60405161023f9190612550565b60405180910390f35b61025061067d565b60405161025d9190612528565b60405180910390f35b610280600480360381019061027b9190612569565b610690565b60405161028d9190612528565b60405180910390f35b61029e6106be565b6040516102ab9190612550565b60405180910390f35b6102bc6106e6565b6040516102c991906125d4565b60405180910390f35b6102da6106ee565b6040516102e79190612605565b60405180910390f35b6102f86106fc565b604051610305919061262d565b60405180910390f35b61032860048036038101906103239190612646565b610720565b60405161033591906126ad565b60405180910390f35b6103466107aa565b604051610353919061262d565b60405180910390f35b6103646107cf565b6040516103719190612550565b60405180910390f35b610394600480360381019061038f9190612646565b6107f7565b6040516103a19190612550565b60405180910390f35b6103b261083c565b005b6103ce60048036038101906103c991906126f0565b610868565b005b6103ea60048036038101906103e59190612646565b61088d565b6040516103f79190612550565b60405180910390f35b61040861089e565b60405161041b979695949392919061280c565b60405180910390f35b61043e600480360381019061043991906124d0565b610943565b005b610448610989565b604051610455919061262d565b60405180910390f35b6104666109b1565b6040516104739190612550565b60405180910390f35b6104966004803603810190610491919061288e565b6109c0565b005b6104a0610ba1565b6040516104ad919061241f565b60405180910390f35b6104d060048036038101906104cb91906124d0565b610c31565b6040516104dd9190612528565b60405180910390f35b61050060048036038101906104fb9190612646565b610c53565b005b61050a610def565b6040516105179190612550565b60405180910390f35b61053a60048036038101906105359190612920565b610df5565b005b6105566004803603810190610551919061288e565b610f3a565b6040516105639190612550565b60405180910390f35b610574610fbc565b6040516105819190612550565b60405180910390f35b6105a4600480360381019061059f9190612646565b610fe3565b005b6105c060048036038101906105bb91906129bd565b611067565b005b6060600380546105d190612a3a565b80601f01602080910402602001604051908101604052809291908181526020018280546105fd90612a3a565b80156106485780601f1061061f57610100808354040283529160200191610648565b820191905f5260205f20905b81548152906001019060200180831161062b57829003601f168201915b5050505050905090565b5f8061065c611109565b9050610669818585611110565b600191505092915050565b5f600254905090565b600a60149054906101000a900460ff1681565b5f8061069a611109565b90506106a7858285611122565b6106b28585856111b4565b60019150509392505050565b6103e860056a396c41bd9e54ada38000006106d99190612a97565b6106e39190612b05565b81565b5f6012905090565b5f6106f76112a4565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610728612379565b600b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff1615151515815250509050919050565b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6103e860056a396c41bd9e54ada38000006107ea9190612a97565b6107f49190612b05565b81565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61084461135a565b5f600a60146101000a81548160ff0219169083151502179055506108666113e1565b565b61087061135a565b80600a60146101000a81548160ff02191690831515021790555050565b5f610897826113f4565b9050919050565b5f6060805f805f60606108af61143a565b6108b7611475565b46305f801b5f67ffffffffffffffff8111156108d6576108d5612b35565b5b6040519080825280602002602001820160405280156109045781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b61094b61135a565b61095582826114b0565b5f61095e610674565b90506a396c41bd9e54ada3800000811115610984576109836303b356bb60e01b61152f565b5b505050565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6a396c41bd9e54ada380000081565b6109c8611537565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610aa9575f8173ffffffffffffffffffffffffffffffffffffffff1647604051610a2090612b8f565b5f6040518083038185875af1925050503d805f8114610a5a576040519150601f19603f3d011682016040523d82523d5f602084013e610a5f565b606091505b5050905080610aa3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9a90612c13565b60405180910390fd5b50610b9d565b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb828473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610aff919061262d565b602060405180830381865afa158015610b1a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3e9190612c45565b6040518363ffffffff1660e01b8152600401610b5b929190612c70565b6020604051808303815f875af1158015610b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9b9190612cab565b505b5050565b606060048054610bb090612a3a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdc90612a3a565b8015610c275780601f10610bfe57610100808354040283529160200191610c27565b820191905f5260205f20905b815481529060010190602001808311610c0a57829003601f168201915b5050505050905090565b5f80610c3b611109565b9050610c488185856111b4565b600191505092915050565b610c5b611537565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060405180604001604052805f151581526020015f1515815250600b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052805f1515815260200160011515815250600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055509050505050565b60095481565b83421115610e3a57836040517f62791302000000000000000000000000000000000000000000000000000000008152600401610e319190612550565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610e688c61159e565b89604051602001610e7e96959493929190612cd6565b6040516020818303038152906040528051906020012090505f610ea0826115f1565b90505f610eaf8287878761160a565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f2357808a6040517f4b800e46000000000000000000000000000000000000000000000000000000008152600401610f1a929190612d35565b60405180910390fd5b610f2e8a8a8a611110565b50505050505050505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b606460016a396c41bd9e54ada3800000610fd69190612a97565b610fe09190612b05565b81565b610feb61135a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361105b575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611052919061262d565b60405180910390fd5b61106481611638565b50565b61106f61135a565b60405180604001604052808315158152602001821515815250600b5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff021916908315150217905550905050505050565b5f33905090565b61111d83838360016116fb565b505050565b5f61112d8484610f3a565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146111ae578181101561119f578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161119693929190612d5c565b60405180910390fd5b6111ad84848484035f6116fb565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611224575f6040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040161121b919061262d565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611294575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161128b919061262d565b60405180910390fd5b61129f8383836118ca565b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614801561131f57507f000000000000000000000000000000000000000000000000000000000000000046145b1561134c577f00000000000000000000000000000000000000000000000000000000000000009050611357565b611354611bea565b90505b90565b611362611109565b73ffffffffffffffffffffffffffffffffffffffff16611380610989565b73ffffffffffffffffffffffffffffffffffffffff16146113df576113a3611109565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016113d6919061262d565b60405180910390fd5b565b6113e961135a565b6113f25f611638565b565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b606061147060057f0000000000000000000000000000000000000000000000000000000000000000611c7f90919063ffffffff16565b905090565b60606114ab60067f0000000000000000000000000000000000000000000000000000000000000000611c7f90919063ffffffff16565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611520575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611517919061262d565b60405180910390fd5b61152b5f83836118ca565b5050565b805f5260045ffd5b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461159c5761159b6310ba399860e01b61152f565b5b565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f6116036115fd6112a4565b83611d2c565b9050919050565b5f805f8061161a88888888611d6c565b92509250925061162a8282611e53565b829350505050949350505050565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361176b575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611762919061262d565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117db575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016117d2919061262d565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555080156118c4578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516118bb9190612550565b60405180910390a35b50505050565b5f600a60149054906101000a900460ff1690505f8290505f600b5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff16151515158152505090505f600b5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581525050905073ae2fc483527b8ef99eb5d9b44875f005ba1fae1373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161480611a6a575073ae2fc483527b8ef99eb5d9b44875f005ba1fae1373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b15611a8057611a7f63c95770fa60e01b61152f565b5b8160200151158015611a9457508060200151155b15611bd657815f015115611b61578315611b3a575f611ab2876107f7565b9050606460016a396c41bd9e54ada3800000611ace9190612a97565b611ad89190612b05565b8682611ae49190612d91565b1115611afb57611afa63276d419b60e01b61152f565b5b6103e860056a396c41bd9e54ada3800000611b169190612a97565b611b209190612b05565b861115611b3857611b3763f216dc0960e01b61152f565b5b505b5f611b4486611fb5565b90508086611b529190612dc4565b9350611b5f8830836120a0565b505b805f015115611bd5578315611bae576103e860056a396c41bd9e54ada3800000611b8b9190612a97565b611b959190612b05565b851115611bad57611bac6371397fb960e01b61152f565b5b5b5f611bb886611fb5565b90508086611bc69190612dc4565b9350611bd38830836120a0565b505b5b611be18787856120a0565b50505050505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001611c64959493929190612df7565b60405160208183030381529060405280519060200120905090565b606060ff5f1b8314611c9b57611c94836122b9565b9050611d26565b818054611ca790612a3a565b80601f0160208091040260200160405190810160405280929190818152602001828054611cd390612a3a565b8015611d1e5780601f10611cf557610100808354040283529160200191611d1e565b820191905f5260205f20905b815481529060010190602001808311611d0157829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115611da8575f600385925092509250611e49565b5f6001888888886040515f8152602001604052604051611dcb9493929190612e48565b6020604051602081039080840390855afa158015611deb573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e3c575f60015f801b93509350935050611e49565b805f805f1b935093509350505b9450945094915050565b5f6003811115611e6657611e65612e8b565b5b826003811115611e7957611e78612e8b565b5b0315611fb15760016003811115611e9357611e92612e8b565b5b826003811115611ea657611ea5612e8b565b5b03611edd576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115611ef157611ef0612e8b565b5b826003811115611f0457611f03612e8b565b5b03611f4857805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401611f3f9190612550565b60405180910390fd5b600380811115611f5b57611f5a612e8b565b5b826003811115611f6e57611f6d612e8b565b5b03611fb057806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401611fa79190612605565b60405180910390fd5b5b5050565b5f8060095490505f8103611feb57426009819055506064600a84611fd99190612a97565b611fe39190612b05565b91505061209b565b5f8142611ff89190612dc4565b9050603c811015612025576064600a856120129190612a97565b61201c9190612b05565b9250505061209b565b61025881101561205157606460058561203e9190612a97565b6120489190612b05565b9250505061209b565b610e1081101561207d57606460038561206a9190612a97565b6120749190612b05565b9250505061209b565b606460028561208c9190612a97565b6120969190612b05565b925050505b919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036120f0578060025f8282546120e49190612d91565b925050819055506121be565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612179578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161217093929190612d5c565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612205578060025f828254039250508190555061224f565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516122ac9190612550565b60405180910390a3505050565b60605f6122c58361232b565b90505f602067ffffffffffffffff8111156122e3576122e2612b35565b5b6040519080825280601f01601f1916602001820160405280156123155781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f8060ff835f1c169050601f811115612370576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60405180604001604052805f151581526020015f151581525090565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156123cc5780820151818401526020810190506123b1565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6123f182612395565b6123fb818561239f565b935061240b8185602086016123af565b612414816123d7565b840191505092915050565b5f6020820190508181035f83015261243781846123e7565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61246c82612443565b9050919050565b61247c81612462565b8114612486575f80fd5b50565b5f8135905061249781612473565b92915050565b5f819050919050565b6124af8161249d565b81146124b9575f80fd5b50565b5f813590506124ca816124a6565b92915050565b5f80604083850312156124e6576124e561243f565b5b5f6124f385828601612489565b9250506020612504858286016124bc565b9150509250929050565b5f8115159050919050565b6125228161250e565b82525050565b5f60208201905061253b5f830184612519565b92915050565b61254a8161249d565b82525050565b5f6020820190506125635f830184612541565b92915050565b5f805f606084860312156125805761257f61243f565b5b5f61258d86828701612489565b935050602061259e86828701612489565b92505060406125af868287016124bc565b9150509250925092565b5f60ff82169050919050565b6125ce816125b9565b82525050565b5f6020820190506125e75f8301846125c5565b92915050565b5f819050919050565b6125ff816125ed565b82525050565b5f6020820190506126185f8301846125f6565b92915050565b61262781612462565b82525050565b5f6020820190506126405f83018461261e565b92915050565b5f6020828403121561265b5761265a61243f565b5b5f61266884828501612489565b91505092915050565b61267a8161250e565b82525050565b604082015f8201516126945f850182612671565b5060208201516126a76020850182612671565b50505050565b5f6040820190506126c05f830184612680565b92915050565b6126cf8161250e565b81146126d9575f80fd5b50565b5f813590506126ea816126c6565b92915050565b5f602082840312156127055761270461243f565b5b5f612712848285016126dc565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61274f8161271b565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6127878161249d565b82525050565b5f612798838361277e565b60208301905092915050565b5f602082019050919050565b5f6127ba82612755565b6127c4818561275f565b93506127cf8361276f565b805f5b838110156127ff5781516127e6888261278d565b97506127f1836127a4565b9250506001810190506127d2565b5085935050505092915050565b5f60e08201905061281f5f83018a612746565b818103602083015261283181896123e7565b9050818103604083015261284581886123e7565b90506128546060830187612541565b612861608083018661261e565b61286e60a08301856125f6565b81810360c083015261288081846127b0565b905098975050505050505050565b5f80604083850312156128a4576128a361243f565b5b5f6128b185828601612489565b92505060206128c285828601612489565b9150509250929050565b6128d5816125b9565b81146128df575f80fd5b50565b5f813590506128f0816128cc565b92915050565b6128ff816125ed565b8114612909575f80fd5b50565b5f8135905061291a816128f6565b92915050565b5f805f805f805f60e0888a03121561293b5761293a61243f565b5b5f6129488a828b01612489565b97505060206129598a828b01612489565b965050604061296a8a828b016124bc565b955050606061297b8a828b016124bc565b945050608061298c8a828b016128e2565b93505060a061299d8a828b0161290c565b92505060c06129ae8a828b0161290c565b91505092959891949750929550565b5f805f606084860312156129d4576129d361243f565b5b5f6129e186828701612489565b93505060206129f2868287016126dc565b9250506040612a03868287016126dc565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612a5157607f821691505b602082108103612a6457612a63612a0d565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612aa18261249d565b9150612aac8361249d565b9250828202612aba8161249d565b91508282048414831517612ad157612ad0612a6a565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612b0f8261249d565b9150612b1a8361249d565b925082612b2a57612b29612ad8565b5b828204905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81905092915050565b50565b5f612b7a5f83612b62565b9150612b8582612b6c565b5f82019050919050565b5f612b9982612b6f565b9150819050919050565b7f776974686472617745524332303a20455448207472616e73666572206661696c5f8201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b5f612bfd60228361239f565b9150612c0882612ba3565b604082019050919050565b5f6020820190508181035f830152612c2a81612bf1565b9050919050565b5f81519050612c3f816124a6565b92915050565b5f60208284031215612c5a57612c5961243f565b5b5f612c6784828501612c31565b91505092915050565b5f604082019050612c835f83018561261e565b612c906020830184612541565b9392505050565b5f81519050612ca5816126c6565b92915050565b5f60208284031215612cc057612cbf61243f565b5b5f612ccd84828501612c97565b91505092915050565b5f60c082019050612ce95f8301896125f6565b612cf6602083018861261e565b612d03604083018761261e565b612d106060830186612541565b612d1d6080830185612541565b612d2a60a0830184612541565b979650505050505050565b5f604082019050612d485f83018561261e565b612d55602083018461261e565b9392505050565b5f606082019050612d6f5f83018661261e565b612d7c6020830185612541565b612d896040830184612541565b949350505050565b5f612d9b8261249d565b9150612da68361249d565b9250828201905080821115612dbe57612dbd612a6a565b5b92915050565b5f612dce8261249d565b9150612dd98361249d565b9250828203905081811115612df157612df0612a6a565b5b92915050565b5f60a082019050612e0a5f8301886125f6565b612e1760208301876125f6565b612e2460408301866125f6565b612e316060830185612541565b612e3e608083018461261e565b9695505050505050565b5f608082019050612e5b5f8301876125f6565b612e6860208301866125c5565b612e7560408301856125f6565b612e8260608301846125f6565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffdfea26469706673582212209445498aa666da2695d479dec544c428e0849687cc06138c2b124cb19090869264736f6c634300081700330000000000000000000000004b2adfca850ef1b1a425572f552bb9b35af63d61
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101d8575f3560e01c80637ecebe0011610102578063a9059cbb116100a0578063dd62ed3e1161006f578063dd62ed3e1461053c578063e56cfceb1461056c578063f2fde38b1461058a578063fcfcd59f146105a6576101d8565b8063a9059cbb146104b6578063ac238956146104e6578063cacf66ab14610502578063d505accf14610520576101d8565b80638da5cb5b116100dc5780638da5cb5b14610440578063902d55a51461045e5780639456fbcc1461047c57806395d89b4114610498576101d8565b80637ecebe00146103d057806384b0196e146104005780638ba4cc3c14610424576101d8565b80633644e5151161017a578063699df72611610149578063699df7261461035c57806370a082311461037a578063715018a6146103aa578063797de370146103b4576101d8565b80633644e515146102d257806349bd5a5e146102f05780635fb5fe3b1461030e578063650a92cb1461033e576101d8565b80631c42047a116101b65780631c42047a1461024857806323b872dd146102665780632492722614610296578063313ce567146102b4576101d8565b806306fdde03146101dc578063095ea7b3146101fa57806318160ddd1461022a575b5f80fd5b6101e46105c2565b6040516101f1919061241f565b60405180910390f35b610214600480360381019061020f91906124d0565b610652565b6040516102219190612528565b60405180910390f35b610232610674565b60405161023f9190612550565b60405180910390f35b61025061067d565b60405161025d9190612528565b60405180910390f35b610280600480360381019061027b9190612569565b610690565b60405161028d9190612528565b60405180910390f35b61029e6106be565b6040516102ab9190612550565b60405180910390f35b6102bc6106e6565b6040516102c991906125d4565b60405180910390f35b6102da6106ee565b6040516102e79190612605565b60405180910390f35b6102f86106fc565b604051610305919061262d565b60405180910390f35b61032860048036038101906103239190612646565b610720565b60405161033591906126ad565b60405180910390f35b6103466107aa565b604051610353919061262d565b60405180910390f35b6103646107cf565b6040516103719190612550565b60405180910390f35b610394600480360381019061038f9190612646565b6107f7565b6040516103a19190612550565b60405180910390f35b6103b261083c565b005b6103ce60048036038101906103c991906126f0565b610868565b005b6103ea60048036038101906103e59190612646565b61088d565b6040516103f79190612550565b60405180910390f35b61040861089e565b60405161041b979695949392919061280c565b60405180910390f35b61043e600480360381019061043991906124d0565b610943565b005b610448610989565b604051610455919061262d565b60405180910390f35b6104666109b1565b6040516104739190612550565b60405180910390f35b6104966004803603810190610491919061288e565b6109c0565b005b6104a0610ba1565b6040516104ad919061241f565b60405180910390f35b6104d060048036038101906104cb91906124d0565b610c31565b6040516104dd9190612528565b60405180910390f35b61050060048036038101906104fb9190612646565b610c53565b005b61050a610def565b6040516105179190612550565b60405180910390f35b61053a60048036038101906105359190612920565b610df5565b005b6105566004803603810190610551919061288e565b610f3a565b6040516105639190612550565b60405180910390f35b610574610fbc565b6040516105819190612550565b60405180910390f35b6105a4600480360381019061059f9190612646565b610fe3565b005b6105c060048036038101906105bb91906129bd565b611067565b005b6060600380546105d190612a3a565b80601f01602080910402602001604051908101604052809291908181526020018280546105fd90612a3a565b80156106485780601f1061061f57610100808354040283529160200191610648565b820191905f5260205f20905b81548152906001019060200180831161062b57829003601f168201915b5050505050905090565b5f8061065c611109565b9050610669818585611110565b600191505092915050565b5f600254905090565b600a60149054906101000a900460ff1681565b5f8061069a611109565b90506106a7858285611122565b6106b28585856111b4565b60019150509392505050565b6103e860056a396c41bd9e54ada38000006106d99190612a97565b6106e39190612b05565b81565b5f6012905090565b5f6106f76112a4565b905090565b7f000000000000000000000000c2fdf6501963f25fae8c869bdd6dce741cce8c5881565b610728612379565b600b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff1615151515815250509050919050565b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6103e860056a396c41bd9e54ada38000006107ea9190612a97565b6107f49190612b05565b81565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61084461135a565b5f600a60146101000a81548160ff0219169083151502179055506108666113e1565b565b61087061135a565b80600a60146101000a81548160ff02191690831515021790555050565b5f610897826113f4565b9050919050565b5f6060805f805f60606108af61143a565b6108b7611475565b46305f801b5f67ffffffffffffffff8111156108d6576108d5612b35565b5b6040519080825280602002602001820160405280156109045781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b61094b61135a565b61095582826114b0565b5f61095e610674565b90506a396c41bd9e54ada3800000811115610984576109836303b356bb60e01b61152f565b5b505050565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6a396c41bd9e54ada380000081565b6109c8611537565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610aa9575f8173ffffffffffffffffffffffffffffffffffffffff1647604051610a2090612b8f565b5f6040518083038185875af1925050503d805f8114610a5a576040519150601f19603f3d011682016040523d82523d5f602084013e610a5f565b606091505b5050905080610aa3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9a90612c13565b60405180910390fd5b50610b9d565b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb828473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610aff919061262d565b602060405180830381865afa158015610b1a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3e9190612c45565b6040518363ffffffff1660e01b8152600401610b5b929190612c70565b6020604051808303815f875af1158015610b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9b9190612cab565b505b5050565b606060048054610bb090612a3a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdc90612a3a565b8015610c275780601f10610bfe57610100808354040283529160200191610c27565b820191905f5260205f20905b815481529060010190602001808311610c0a57829003601f168201915b5050505050905090565b5f80610c3b611109565b9050610c488185856111b4565b600191505092915050565b610c5b611537565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060405180604001604052805f151581526020015f1515815250600b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff02191690831515021790555090505081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052805f1515815260200160011515815250600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055509050505050565b60095481565b83421115610e3a57836040517f62791302000000000000000000000000000000000000000000000000000000008152600401610e319190612550565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610e688c61159e565b89604051602001610e7e96959493929190612cd6565b6040516020818303038152906040528051906020012090505f610ea0826115f1565b90505f610eaf8287878761160a565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f2357808a6040517f4b800e46000000000000000000000000000000000000000000000000000000008152600401610f1a929190612d35565b60405180910390fd5b610f2e8a8a8a611110565b50505050505050505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b606460016a396c41bd9e54ada3800000610fd69190612a97565b610fe09190612b05565b81565b610feb61135a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361105b575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611052919061262d565b60405180910390fd5b61106481611638565b50565b61106f61135a565b60405180604001604052808315158152602001821515815250600b5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff021916908315150217905550905050505050565b5f33905090565b61111d83838360016116fb565b505050565b5f61112d8484610f3a565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146111ae578181101561119f578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161119693929190612d5c565b60405180910390fd5b6111ad84848484035f6116fb565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611224575f6040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040161121b919061262d565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611294575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161128b919061262d565b60405180910390fd5b61129f8383836118ca565b505050565b5f7f0000000000000000000000003f5e5aa8070c860d6d7d951d407a50a3f131931d73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614801561131f57507f000000000000000000000000000000000000000000000000000000000000000146145b1561134c577f6a105ecb0d7205288093e1e38c80bde3281f6fd6f62630122be76a18a086facc9050611357565b611354611bea565b90505b90565b611362611109565b73ffffffffffffffffffffffffffffffffffffffff16611380610989565b73ffffffffffffffffffffffffffffffffffffffff16146113df576113a3611109565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016113d6919061262d565b60405180910390fd5b565b6113e961135a565b6113f25f611638565b565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b606061147060057f48455220436f696e000000000000000000000000000000000000000000000008611c7f90919063ffffffff16565b905090565b60606114ab60067f3100000000000000000000000000000000000000000000000000000000000001611c7f90919063ffffffff16565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611520575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611517919061262d565b60405180910390fd5b61152b5f83836118ca565b5050565b805f5260045ffd5b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461159c5761159b6310ba399860e01b61152f565b5b565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f6116036115fd6112a4565b83611d2c565b9050919050565b5f805f8061161a88888888611d6c565b92509250925061162a8282611e53565b829350505050949350505050565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361176b575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611762919061262d565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117db575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016117d2919061262d565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555080156118c4578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516118bb9190612550565b60405180910390a35b50505050565b5f600a60149054906101000a900460ff1690505f8290505f600b5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff16151515158152505090505f600b5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581525050905073ae2fc483527b8ef99eb5d9b44875f005ba1fae1373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161480611a6a575073ae2fc483527b8ef99eb5d9b44875f005ba1fae1373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b15611a8057611a7f63c95770fa60e01b61152f565b5b8160200151158015611a9457508060200151155b15611bd657815f015115611b61578315611b3a575f611ab2876107f7565b9050606460016a396c41bd9e54ada3800000611ace9190612a97565b611ad89190612b05565b8682611ae49190612d91565b1115611afb57611afa63276d419b60e01b61152f565b5b6103e860056a396c41bd9e54ada3800000611b169190612a97565b611b209190612b05565b861115611b3857611b3763f216dc0960e01b61152f565b5b505b5f611b4486611fb5565b90508086611b529190612dc4565b9350611b5f8830836120a0565b505b805f015115611bd5578315611bae576103e860056a396c41bd9e54ada3800000611b8b9190612a97565b611b959190612b05565b851115611bad57611bac6371397fb960e01b61152f565b5b5b5f611bb886611fb5565b90508086611bc69190612dc4565b9350611bd38830836120a0565b505b5b611be18787856120a0565b50505050505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f89e44cd4827bf1d34c43580f35db302d0da8c93a1834878b74d660e25db212797fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001611c64959493929190612df7565b60405160208183030381529060405280519060200120905090565b606060ff5f1b8314611c9b57611c94836122b9565b9050611d26565b818054611ca790612a3a565b80601f0160208091040260200160405190810160405280929190818152602001828054611cd390612a3a565b8015611d1e5780601f10611cf557610100808354040283529160200191611d1e565b820191905f5260205f20905b815481529060010190602001808311611d0157829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115611da8575f600385925092509250611e49565b5f6001888888886040515f8152602001604052604051611dcb9493929190612e48565b6020604051602081039080840390855afa158015611deb573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e3c575f60015f801b93509350935050611e49565b805f805f1b935093509350505b9450945094915050565b5f6003811115611e6657611e65612e8b565b5b826003811115611e7957611e78612e8b565b5b0315611fb15760016003811115611e9357611e92612e8b565b5b826003811115611ea657611ea5612e8b565b5b03611edd576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115611ef157611ef0612e8b565b5b826003811115611f0457611f03612e8b565b5b03611f4857805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401611f3f9190612550565b60405180910390fd5b600380811115611f5b57611f5a612e8b565b5b826003811115611f6e57611f6d612e8b565b5b03611fb057806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401611fa79190612605565b60405180910390fd5b5b5050565b5f8060095490505f8103611feb57426009819055506064600a84611fd99190612a97565b611fe39190612b05565b91505061209b565b5f8142611ff89190612dc4565b9050603c811015612025576064600a856120129190612a97565b61201c9190612b05565b9250505061209b565b61025881101561205157606460058561203e9190612a97565b6120489190612b05565b9250505061209b565b610e1081101561207d57606460038561206a9190612a97565b6120749190612b05565b9250505061209b565b606460028561208c9190612a97565b6120969190612b05565b925050505b919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036120f0578060025f8282546120e49190612d91565b925050819055506121be565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612179578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161217093929190612d5c565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612205578060025f828254039250508190555061224f565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516122ac9190612550565b60405180910390a3505050565b60605f6122c58361232b565b90505f602067ffffffffffffffff8111156122e3576122e2612b35565b5b6040519080825280601f01601f1916602001820160405280156123155781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f8060ff835f1c169050601f811115612370576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60405180604001604052805f151581526020015f151581525090565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156123cc5780820151818401526020810190506123b1565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6123f182612395565b6123fb818561239f565b935061240b8185602086016123af565b612414816123d7565b840191505092915050565b5f6020820190508181035f83015261243781846123e7565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61246c82612443565b9050919050565b61247c81612462565b8114612486575f80fd5b50565b5f8135905061249781612473565b92915050565b5f819050919050565b6124af8161249d565b81146124b9575f80fd5b50565b5f813590506124ca816124a6565b92915050565b5f80604083850312156124e6576124e561243f565b5b5f6124f385828601612489565b9250506020612504858286016124bc565b9150509250929050565b5f8115159050919050565b6125228161250e565b82525050565b5f60208201905061253b5f830184612519565b92915050565b61254a8161249d565b82525050565b5f6020820190506125635f830184612541565b92915050565b5f805f606084860312156125805761257f61243f565b5b5f61258d86828701612489565b935050602061259e86828701612489565b92505060406125af868287016124bc565b9150509250925092565b5f60ff82169050919050565b6125ce816125b9565b82525050565b5f6020820190506125e75f8301846125c5565b92915050565b5f819050919050565b6125ff816125ed565b82525050565b5f6020820190506126185f8301846125f6565b92915050565b61262781612462565b82525050565b5f6020820190506126405f83018461261e565b92915050565b5f6020828403121561265b5761265a61243f565b5b5f61266884828501612489565b91505092915050565b61267a8161250e565b82525050565b604082015f8201516126945f850182612671565b5060208201516126a76020850182612671565b50505050565b5f6040820190506126c05f830184612680565b92915050565b6126cf8161250e565b81146126d9575f80fd5b50565b5f813590506126ea816126c6565b92915050565b5f602082840312156127055761270461243f565b5b5f612712848285016126dc565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61274f8161271b565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6127878161249d565b82525050565b5f612798838361277e565b60208301905092915050565b5f602082019050919050565b5f6127ba82612755565b6127c4818561275f565b93506127cf8361276f565b805f5b838110156127ff5781516127e6888261278d565b97506127f1836127a4565b9250506001810190506127d2565b5085935050505092915050565b5f60e08201905061281f5f83018a612746565b818103602083015261283181896123e7565b9050818103604083015261284581886123e7565b90506128546060830187612541565b612861608083018661261e565b61286e60a08301856125f6565b81810360c083015261288081846127b0565b905098975050505050505050565b5f80604083850312156128a4576128a361243f565b5b5f6128b185828601612489565b92505060206128c285828601612489565b9150509250929050565b6128d5816125b9565b81146128df575f80fd5b50565b5f813590506128f0816128cc565b92915050565b6128ff816125ed565b8114612909575f80fd5b50565b5f8135905061291a816128f6565b92915050565b5f805f805f805f60e0888a03121561293b5761293a61243f565b5b5f6129488a828b01612489565b97505060206129598a828b01612489565b965050604061296a8a828b016124bc565b955050606061297b8a828b016124bc565b945050608061298c8a828b016128e2565b93505060a061299d8a828b0161290c565b92505060c06129ae8a828b0161290c565b91505092959891949750929550565b5f805f606084860312156129d4576129d361243f565b5b5f6129e186828701612489565b93505060206129f2868287016126dc565b9250506040612a03868287016126dc565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612a5157607f821691505b602082108103612a6457612a63612a0d565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612aa18261249d565b9150612aac8361249d565b9250828202612aba8161249d565b91508282048414831517612ad157612ad0612a6a565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612b0f8261249d565b9150612b1a8361249d565b925082612b2a57612b29612ad8565b5b828204905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81905092915050565b50565b5f612b7a5f83612b62565b9150612b8582612b6c565b5f82019050919050565b5f612b9982612b6f565b9150819050919050565b7f776974686472617745524332303a20455448207472616e73666572206661696c5f8201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b5f612bfd60228361239f565b9150612c0882612ba3565b604082019050919050565b5f6020820190508181035f830152612c2a81612bf1565b9050919050565b5f81519050612c3f816124a6565b92915050565b5f60208284031215612c5a57612c5961243f565b5b5f612c6784828501612c31565b91505092915050565b5f604082019050612c835f83018561261e565b612c906020830184612541565b9392505050565b5f81519050612ca5816126c6565b92915050565b5f60208284031215612cc057612cbf61243f565b5b5f612ccd84828501612c97565b91505092915050565b5f60c082019050612ce95f8301896125f6565b612cf6602083018861261e565b612d03604083018761261e565b612d106060830186612541565b612d1d6080830185612541565b612d2a60a0830184612541565b979650505050505050565b5f604082019050612d485f83018561261e565b612d55602083018461261e565b9392505050565b5f606082019050612d6f5f83018661261e565b612d7c6020830185612541565b612d896040830184612541565b949350505050565b5f612d9b8261249d565b9150612da68361249d565b9250828201905080821115612dbe57612dbd612a6a565b5b92915050565b5f612dce8261249d565b9150612dd98361249d565b9250828203905081811115612df157612df0612a6a565b5b92915050565b5f60a082019050612e0a5f8301886125f6565b612e1760208301876125f6565b612e2460408301866125f6565b612e316060830185612541565b612e3e608083018461261e565b9695505050505050565b5f608082019050612e5b5f8301876125f6565b612e6860208301866125c5565b612e7560408301856125f6565b612e8260608301846125f6565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffdfea26469706673582212209445498aa666da2695d479dec544c428e0849687cc06138c2b124cb19090869264736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004b2adfca850ef1b1a425572f552bb9b35af63d61
-----Decoded View---------------
Arg [0] : _owner (address): 0x4b2ADfCa850EF1b1a425572F552bb9B35aF63d61
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004b2adfca850ef1b1a425572f552bb9b35af63d61
Deployed Bytecode Sourcemap
83968:14757:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71566:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73859:190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72668:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;86632:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;74627:249;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85219:82;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72519:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83419:114;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85802:38;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94723:130;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;86396:73;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85080:81;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72830:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94305:126;;;:::i;:::-;;94054:99;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;83161:145;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41798:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;91429:293;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;64504:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84864:55;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92171:389;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71776:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73153:182;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92999:376;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;86275:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;82407:695;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;73398:142;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84926:96;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;65437:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;93680:227;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71566:91;71611:13;71644:5;71637:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71566:91;:::o;73859:190::-;73932:4;73949:13;73965:12;:10;:12::i;:::-;73949:28;;73988:31;73997:5;74004:7;74013:5;73988:8;:31::i;:::-;74037:4;74030:11;;;73859:190;;;;:::o;72668:99::-;72720:7;72747:12;;72740:19;;72668:99;:::o;86632:28::-;;;;;;;;;;;;;:::o;74627:249::-;74714:4;74731:15;74749:12;:10;:12::i;:::-;74731:30;;74772:37;74788:4;74794:7;74803:5;74772:15;:37::i;:::-;74820:26;74830:4;74836:2;74840:5;74820:9;:26::i;:::-;74864:4;74857:11;;;74627:249;;;;;:::o;85219:82::-;85296:4;85283:1;84903:16;85260:25;;;;:::i;:::-;:41;;;;:::i;:::-;85219:82;:::o;72519:84::-;72568:5;72593:2;72586:9;;72519:84;:::o;83419:114::-;83478:7;83505:20;:18;:20::i;:::-;83498:27;;83419:114;:::o;85802:38::-;;;:::o;94723:130::-;94785:18;;:::i;:::-;94823:12;:22;94836:8;94823:22;;;;;;;;;;;;;;;94816:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94723:130;;;:::o;86396:73::-;;;;;;;;;;;;;:::o;85080:81::-;85156:4;85143:1;84903:16;85120:25;;;;:::i;:::-;:41;;;;:::i;:::-;85080:81;:::o;72830:118::-;72895:7;72922:9;:18;72932:7;72922:18;;;;;;;;;;;;;;;;72915:25;;72830:118;;;:::o;94305:126::-;64390:13;:11;:13::i;:::-;94382:5:::1;94371:8;;:16;;;;;;;;;;;;;;;;;;94398:25;:23;:25::i;:::-;94305:126::o:0;94054:99::-;64390:13;:11;:13::i;:::-;94136:9:::1;94125:8;;:20;;;;;;;;;;;;;;;;;;94054:99:::0;:::o;83161:145::-;83252:7;83279:19;83292:5;83279:12;:19::i;:::-;83272:26;;83161:145;;;:::o;41798:580::-;41901:13;41929:18;41962:21;41998:15;42028:25;42068:12;42095:27;42203:13;:11;:13::i;:::-;42231:16;:14;:16::i;:::-;42262:13;42298:4;42326:1;42318:10;;42357:1;42343:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42150:220;;;;;;;;;;;;;;;;;;;;;41798:580;;;;;;;:::o;91429:293::-;64390:13;:11;:13::i;:::-;91515:24:::1;91521:8;91531:7;91515:5;:24::i;:::-;91564:22;91589:13;:11;:13::i;:::-;91564:38;;84903:16;91617:14;:29;91613:102;;;91663:40;91671:31;;;91663:7;:40::i;:::-;91613:102;91500:222;91429:293:::0;;:::o;64504:87::-;64550:7;64577:6;;;;;;;;;;;64570:13;;64504:87;:::o;84864:55::-;84903:16;84864:55;:::o;92171:389::-;92242:21;:19;:21::i;:::-;92296:1;92278:20;;:6;:20;;;92274:279;;92316:7;92336:2;92328:16;;92352:21;92328:50;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92315:63;;;92401:2;92393:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;92300:154;92274:279;;;92481:6;92475:22;;;92498:2;92508:6;92502:23;;;92534:4;92502:38;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92475:66;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;92274:279;92171:389;;:::o;71776:95::-;71823:13;71856:7;71849:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71776:95;:::o;73153:182::-;73222:4;73239:13;73255:12;:10;:12::i;:::-;73239:28;;73278:27;73288:5;73295:2;73299:5;73278:9;:27::i;:::-;73323:4;73316:11;;;73153:182;;;;:::o;92999:376::-;93069:21;:19;:21::i;:::-;93101:20;93124:13;;;;;;;;;;;93101:36;;93177:54;;;;;;;;93198:5;93177:54;;;;;;93224:5;93177:54;;;;;93148:12;:26;93161:12;93148:26;;;;;;;;;;;;;;;:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93258:14;93242:13;;:30;;;;;;;;;;;;;;;;;;93314:53;;;;;;;;93335:5;93314:53;;;;;;93361:4;93314:53;;;;;93283:12;:28;93296:14;93283:28;;;;;;;;;;;;;;;:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93058:317;92999:376;:::o;86275:31::-;;;;:::o;82407:695::-;82637:8;82619:15;:26;82615:99;;;82693:8;82669:33;;;;;;;;;;;:::i;:::-;;;;;;;;82615:99;82726:18;81727:95;82785:5;82792:7;82801:5;82808:16;82818:5;82808:9;:16::i;:::-;82826:8;82757:78;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;82747:89;;;;;;82726:110;;82849:12;82864:28;82881:10;82864:16;:28::i;:::-;82849:43;;82905:14;82922:28;82936:4;82942:1;82945;82948;82922:13;:28::i;:::-;82905:45;;82975:5;82965:15;;:6;:15;;;82961:90;;83025:6;83033:5;83004:35;;;;;;;;;;;;:::i;:::-;;;;;;;;82961:90;83063:31;83072:5;83079:7;83088:5;83063:8;:31::i;:::-;82604:498;;;82407:695;;;;;;;:::o;73398:142::-;73478:7;73505:11;:18;73517:5;73505:18;;;;;;;;;;;;;;;:27;73524:7;73505:27;;;;;;;;;;;;;;;;73498:34;;73398:142;;;;:::o;84926:96::-;85018:3;85005:1;84903:16;84982:25;;;;:::i;:::-;:40;;;;:::i;:::-;84926:96;:::o;65437:220::-;64390:13;:11;:13::i;:::-;65542:1:::1;65522:22;;:8;:22;;::::0;65518:93:::1;;65596:1;65568:31;;;;;;;;;;;:::i;:::-;;;;;;;;65518:93;65621:28;65640:8;65621:18;:28::i;:::-;65437:220:::0;:::o;93680:227::-;64390:13;:11;:13::i;:::-;93830:69:::1;;;;;;;;93851:7;93830:69;;;;;;93879:18;93830:69;;;;::::0;93805:12:::1;:22;93818:8;93805:22;;;;;;;;;;;;;;;:94;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93680:227:::0;;;:::o;62620:98::-;62673:7;62700:10;62693:17;;62620:98;:::o;78686:130::-;78771:37;78780:5;78787:7;78796:5;78803:4;78771:8;:37::i;:::-;78686:130;;;:::o;80402:487::-;80502:24;80529:25;80539:5;80546:7;80529:9;:25::i;:::-;80502:52;;80589:17;80569:16;:37;80565:317;;80646:5;80627:16;:24;80623:132;;;80706:7;80715:16;80733:5;80679:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;80623:132;80798:57;80807:5;80814:7;80842:5;80823:16;:24;80849:5;80798:8;:57::i;:::-;80565:317;80491:398;80402:487;;;:::o;75261:308::-;75361:1;75345:18;;:4;:18;;;75341:88;;75414:1;75387:30;;;;;;;;;;;:::i;:::-;;;;;;;;75341:88;75457:1;75443:16;;:2;:16;;;75439:88;;75512:1;75483:32;;;;;;;;;;;:::i;:::-;;;;;;;;75439:88;75537:24;75545:4;75551:2;75555:5;75537:7;:24::i;:::-;75261:308;;;:::o;40465:268::-;40518:7;40559:11;40542:28;;40550:4;40542:28;;;:63;;;;;40591:14;40574:13;:31;40542:63;40538:188;;;40629:22;40622:29;;;;40538:188;40691:23;:21;:23::i;:::-;40684:30;;40465:268;;:::o;64669:166::-;64740:12;:10;:12::i;:::-;64729:23;;:7;:5;:7::i;:::-;:23;;;64725:103;;64803:12;:10;:12::i;:::-;64776:40;;;;;;;;;;;:::i;:::-;;;;;;;;64725:103;64669:166::o;65179:103::-;64390:13;:11;:13::i;:::-;65244:30:::1;65271:1;65244:18;:30::i;:::-;65179:103::o:0;2513:109::-;2573:7;2600;:14;2608:5;2600:14;;;;;;;;;;;;;;;;2593:21;;2513:109;;;:::o;42707:128::-;42753:13;42786:41;42813:13;42786:5;:26;;:41;;;;:::i;:::-;42779:48;;42707:128;:::o;43170:137::-;43219:13;43252:47;43282:16;43252:8;:29;;:47;;;;:::i;:::-;43245:54;;43170:137;:::o;77381:213::-;77471:1;77452:21;;:7;:21;;;77448:93;;77526:1;77497:32;;;;;;;;;;;:::i;:::-;;;;;;;;77448:93;77551:35;77567:1;77571:7;77580:5;77551:7;:35::i;:::-;77381:213;;:::o;98571:151::-;98665:8;98660:3;98653:21;98700:3;98695;98688:16;98288:160;98362:13;;;;;;;;;;;98348:27;;:10;:27;;;98344:97;;98392:37;98400:28;;;98392:7;:37::i;:::-;98344:97;98288:160::o;2743:402::-;2803:7;3110;:14;3118:5;3110:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;3103:23;;2743:402;;;:::o;41564:178::-;41641:7;41668:66;41701:20;:18;:20::i;:::-;41723:10;41668:32;:66::i;:::-;41661:73;;41564:178;;;:::o;50304:264::-;50389:7;50410:17;50429:18;50449:16;50469:25;50480:4;50486:1;50489;50492;50469:10;:25::i;:::-;50409:85;;;;;;50505:28;50517:5;50524:8;50505:11;:28::i;:::-;50551:9;50544:16;;;;;50304:264;;;;;;:::o;65817:191::-;65891:16;65910:6;;;;;;;;;;;65891:25;;65936:8;65927:6;;:17;;;;;;;;;;;;;;;;;;65991:8;65960:40;;65981:8;65960:40;;;;;;;;;;;;65880:128;65817:191;:::o;79667:443::-;79797:1;79780:19;;:5;:19;;;79776:91;;79852:1;79823:32;;;;;;;;;;;:::i;:::-;;;;;;;;79776:91;79900:1;79881:21;;:7;:21;;;79877:92;;79954:1;79926:31;;;;;;;;;;;:::i;:::-;;;;;;;;79877:92;80009:5;79979:11;:18;79991:5;79979:18;;;;;;;;;;;;;;;:27;79998:7;79979:27;;;;;;;;;;;;;;;:35;;;;80029:9;80025:78;;;80076:7;80060:31;;80069:5;80060:31;;;80085:5;80060:31;;;;;;:::i;:::-;;;;;;;;80025:78;79667:443;;;;:::o;89354:1543::-;89448:14;89465:8;;;;;;;;;;;89448:25;;89484:14;89501:5;89484:22;;89517:27;89547:12;:18;89560:4;89547:18;;;;;;;;;;;;;;;89517:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89576:25;89604:12;:16;89617:2;89604:16;;;;;;;;;;;;;;;89576:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85395:42;89635:13;;:4;:13;;;:28;;;;85395:42;89652:11;;:2;:11;;;89635:28;89631:99;;;89680:38;89688:29;;;89680:7;:38::i;:::-;89631:99;89745:8;:26;;;89744:27;:56;;;;;89776:6;:24;;;89775:25;89744:56;89740:1106;;;89821:8;:15;;;89817:617;;;89861:9;89857:410;;;89895:17;89915:13;89925:2;89915:9;:13::i;:::-;89895:33;;85018:3;85005:1;84903:16;84982:25;;;;:::i;:::-;:40;;;;:::i;:::-;89967:5;89955:9;:17;;;;:::i;:::-;:49;89951:148;;;90033:42;90041:33;;;90033:7;:42::i;:::-;89951:148;85156:4;85143:1;84903:16;85120:25;;;;:::i;:::-;:41;;;;:::i;:::-;90125:5;:21;90121:127;;;90175:49;90183:40;;;90175:7;:49::i;:::-;90121:127;89872:395;89857:410;90287:11;90301:18;90313:5;90301:11;:18::i;:::-;90287:32;;90355:3;90347:5;:11;;;;:::i;:::-;90338:20;;90379:39;90393:4;90407;90414:3;90379:13;:39::i;:::-;89838:596;89817:617;90452:6;:13;;;90448:387;;;90490:9;90486:186;;;85296:4;85283:1;84903:16;85260:25;;;;:::i;:::-;:41;;;;:::i;:::-;90528:5;:22;90524:129;;;90579:50;90587:41;;;90579:7;:50::i;:::-;90524:129;90486:186;90690:11;90704:18;90716:5;90704:11;:18::i;:::-;90690:32;;90758:3;90750:5;:11;;;;:::i;:::-;90741:20;;90780:39;90794:4;90808;90815:3;90780:13;:39::i;:::-;90467:368;90448:387;89740:1106;90858:31;90872:4;90878:2;90882:6;90858:13;:31::i;:::-;89437:1460;;;;89354:1543;;;:::o;40741:181::-;40796:7;38657:95;40855:11;40868:14;40884:13;40907:4;40833:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;40823:91;;;;;;40816:98;;40741:181;:::o;11853:273::-;11947:13;9799:66;12006:17;;11996:5;11977:46;11973:146;;12047:15;12056:5;12047:8;:15::i;:::-;12040:22;;;;11973:146;12102:5;12095:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11853:273;;;;;:::o;36264:410::-;36357:14;36469:4;36463:11;36500:10;36495:3;36488:23;36548:15;36541:4;36536:3;36532:14;36525:39;36601:10;36594:4;36589:3;36585:14;36578:34;36651:4;36646:3;36636:20;36626:30;;36437:230;36264:410;;;;:::o;48609:1556::-;48740:7;48749:12;48763:7;49683:66;49678:1;49670:10;;:79;49666:166;;;49782:1;49786:30;49818:1;49766:54;;;;;;;;49666:166;49929:14;49946:24;49956:4;49962:1;49965;49968;49946:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49929:41;;50003:1;49985:20;;:6;:20;;;49981:115;;50038:1;50042:29;50081:1;50073:10;;50022:62;;;;;;;;;49981:115;50116:6;50124:20;50154:1;50146:10;;50108:49;;;;;;;48609:1556;;;;;;;;;:::o;50706:542::-;50802:20;50793:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;50789:452;50839:7;50789:452;50900:29;50891:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;50887:354;;50953:23;;;;;;;;;;;;;;50887:354;51007:35;50998:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;50994:247;;51102:8;51094:17;;51066:46;;;;;;;;;;;:::i;:::-;;;;;;;;50994:247;51143:30;51134:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;51130:111;;51220:8;51197:32;;;;;;;;;;;:::i;:::-;;;;;;;;51130:111;50706:542;;;:::o;96932:774::-;96987:7;97007:25;97035:16;;97007:44;;97087:1;97066:17;:22;97062:140;;97124:15;97105:16;:34;;;;97177:3;97171:2;97162:6;:11;;;;:::i;:::-;97161:19;;;;:::i;:::-;97154:26;;;;;97062:140;97212:26;97259:17;97241:15;:35;;;;:::i;:::-;97212:64;;97312:2;97291:18;:23;97287:116;;;97378:3;97372:2;97363:6;:11;;;;:::i;:::-;97362:19;;;;:::i;:::-;97355:26;;;;;;97287:116;97438:3;97417:18;:24;97413:117;;;97506:3;97501:1;97492:6;:10;;;;:::i;:::-;97491:18;;;;:::i;:::-;97484:25;;;;;;97413:117;97587:4;97566:18;:25;97562:92;;;97630:3;97625:1;97616:6;:10;;;;:::i;:::-;97615:18;;;;:::i;:::-;97608:25;;;;;;97562:92;97686:3;97681:1;97672:6;:10;;;;:::i;:::-;97671:18;;;;:::i;:::-;97664:25;;;;96932:774;;;;:::o;75893:1135::-;75999:1;75983:18;;:4;:18;;;75979:552;;76137:5;76121:12;;:21;;;;;;;:::i;:::-;;;;;;;;75979:552;;;76175:19;76197:9;:15;76207:4;76197:15;;;;;;;;;;;;;;;;76175:37;;76245:5;76231:11;:19;76227:117;;;76303:4;76309:11;76322:5;76278:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;76227:117;76499:5;76485:11;:19;76467:9;:15;76477:4;76467:15;;;;;;;;;;;;;;;:37;;;;76160:371;75979:552;76561:1;76547:16;;:2;:16;;;76543:435;;76729:5;76713:12;;:21;;;;;;;;;;;76543:435;;;76946:5;76929:9;:13;76939:2;76929:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;76543:435;77010:2;76995:25;;77004:4;76995:25;;;77014:5;76995:25;;;;;;:::i;:::-;;;;;;;;75893:1135;;;:::o;10508:415::-;10567:13;10593:11;10607:16;10618:4;10607:10;:16::i;:::-;10593:30;;10713:17;10744:2;10733:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10713:34;;10838:3;10833;10826:16;10879:4;10872;10867:3;10863:14;10856:28;10912:3;10905:10;;;;10508:415;;;:::o;11000:251::-;11061:7;11081:14;11134:4;11125;11098:33;;:40;11081:57;;11162:2;11153:6;:11;11149:71;;;11188:20;;;;;;;;;;;;;;11149:71;11237:6;11230:13;;;11000:251;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;:::o;7:99:1:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:246::-;368:1;378:113;392:6;389:1;386:13;378:113;;;477:1;472:3;468:11;462:18;458:1;453:3;449:11;442:39;414:2;411:1;407:10;402:15;;378:113;;;525:1;516:6;511:3;507:16;500:27;349:184;287:246;;;:::o;539:102::-;580:6;631:2;627:7;622:2;615:5;611:14;607:28;597:38;;539:102;;;:::o;647:377::-;735:3;763:39;796:5;763:39;:::i;:::-;818:71;882:6;877:3;818:71;:::i;:::-;811:78;;898:65;956:6;951:3;944:4;937:5;933:16;898:65;:::i;:::-;988:29;1010:6;988:29;:::i;:::-;983:3;979:39;972:46;;739:285;647:377;;;;:::o;1030:313::-;1143:4;1181:2;1170:9;1166:18;1158:26;;1230:9;1224:4;1220:20;1216:1;1205:9;1201:17;1194:47;1258:78;1331:4;1322:6;1258:78;:::i;:::-;1250:86;;1030:313;;;;:::o;1430:117::-;1539:1;1536;1529:12;1676:126;1713:7;1753:42;1746:5;1742:54;1731:65;;1676:126;;;:::o;1808:96::-;1845:7;1874:24;1892:5;1874:24;:::i;:::-;1863:35;;1808:96;;;:::o;1910:122::-;1983:24;2001:5;1983:24;:::i;:::-;1976:5;1973:35;1963:63;;2022:1;2019;2012:12;1963:63;1910:122;:::o;2038:139::-;2084:5;2122:6;2109:20;2100:29;;2138:33;2165:5;2138:33;:::i;:::-;2038:139;;;;:::o;2183:77::-;2220:7;2249:5;2238:16;;2183:77;;;:::o;2266:122::-;2339:24;2357:5;2339:24;:::i;:::-;2332:5;2329:35;2319:63;;2378:1;2375;2368:12;2319:63;2266:122;:::o;2394:139::-;2440:5;2478:6;2465:20;2456:29;;2494:33;2521:5;2494:33;:::i;:::-;2394:139;;;;:::o;2539:474::-;2607:6;2615;2664:2;2652:9;2643:7;2639:23;2635:32;2632:119;;;2670:79;;:::i;:::-;2632:119;2790:1;2815:53;2860:7;2851:6;2840:9;2836:22;2815:53;:::i;:::-;2805:63;;2761:117;2917:2;2943:53;2988:7;2979:6;2968:9;2964:22;2943:53;:::i;:::-;2933:63;;2888:118;2539:474;;;;;:::o;3019:90::-;3053:7;3096:5;3089:13;3082:21;3071:32;;3019:90;;;:::o;3115:109::-;3196:21;3211:5;3196:21;:::i;:::-;3191:3;3184:34;3115:109;;:::o;3230:210::-;3317:4;3355:2;3344:9;3340:18;3332:26;;3368:65;3430:1;3419:9;3415:17;3406:6;3368:65;:::i;:::-;3230:210;;;;:::o;3446:118::-;3533:24;3551:5;3533:24;:::i;:::-;3528:3;3521:37;3446:118;;:::o;3570:222::-;3663:4;3701:2;3690:9;3686:18;3678:26;;3714:71;3782:1;3771:9;3767:17;3758:6;3714:71;:::i;:::-;3570:222;;;;:::o;3798:619::-;3875:6;3883;3891;3940:2;3928:9;3919:7;3915:23;3911:32;3908:119;;;3946:79;;:::i;:::-;3908:119;4066:1;4091:53;4136:7;4127:6;4116:9;4112:22;4091:53;:::i;:::-;4081:63;;4037:117;4193:2;4219:53;4264:7;4255:6;4244:9;4240:22;4219:53;:::i;:::-;4209:63;;4164:118;4321:2;4347:53;4392:7;4383:6;4372:9;4368:22;4347:53;:::i;:::-;4337:63;;4292:118;3798:619;;;;;:::o;4423:86::-;4458:7;4498:4;4491:5;4487:16;4476:27;;4423:86;;;:::o;4515:112::-;4598:22;4614:5;4598:22;:::i;:::-;4593:3;4586:35;4515:112;;:::o;4633:214::-;4722:4;4760:2;4749:9;4745:18;4737:26;;4773:67;4837:1;4826:9;4822:17;4813:6;4773:67;:::i;:::-;4633:214;;;;:::o;4853:77::-;4890:7;4919:5;4908:16;;4853:77;;;:::o;4936:118::-;5023:24;5041:5;5023:24;:::i;:::-;5018:3;5011:37;4936:118;;:::o;5060:222::-;5153:4;5191:2;5180:9;5176:18;5168:26;;5204:71;5272:1;5261:9;5257:17;5248:6;5204:71;:::i;:::-;5060:222;;;;:::o;5288:118::-;5375:24;5393:5;5375:24;:::i;:::-;5370:3;5363:37;5288:118;;:::o;5412:222::-;5505:4;5543:2;5532:9;5528:18;5520:26;;5556:71;5624:1;5613:9;5609:17;5600:6;5556:71;:::i;:::-;5412:222;;;;:::o;5640:329::-;5699:6;5748:2;5736:9;5727:7;5723:23;5719:32;5716:119;;;5754:79;;:::i;:::-;5716:119;5874:1;5899:53;5944:7;5935:6;5924:9;5920:22;5899:53;:::i;:::-;5889:63;;5845:117;5640:329;;;;:::o;5975:99::-;6046:21;6061:5;6046:21;:::i;:::-;6041:3;6034:34;5975:99;;:::o;6144:518::-;6299:4;6294:3;6290:14;6388:4;6381:5;6377:16;6371:23;6407:57;6458:4;6453:3;6449:14;6435:12;6407:57;:::i;:::-;6314:160;6569:4;6562:5;6558:16;6552:23;6588:57;6639:4;6634:3;6630:14;6616:12;6588:57;:::i;:::-;6484:171;6268:394;6144:518;;:::o;6668:338::-;6819:4;6857:2;6846:9;6842:18;6834:26;;6870:129;6996:1;6985:9;6981:17;6972:6;6870:129;:::i;:::-;6668:338;;;;:::o;7012:116::-;7082:21;7097:5;7082:21;:::i;:::-;7075:5;7072:32;7062:60;;7118:1;7115;7108:12;7062:60;7012:116;:::o;7134:133::-;7177:5;7215:6;7202:20;7193:29;;7231:30;7255:5;7231:30;:::i;:::-;7134:133;;;;:::o;7273:323::-;7329:6;7378:2;7366:9;7357:7;7353:23;7349:32;7346:119;;;7384:79;;:::i;:::-;7346:119;7504:1;7529:50;7571:7;7562:6;7551:9;7547:22;7529:50;:::i;:::-;7519:60;;7475:114;7273:323;;;;:::o;7602:149::-;7638:7;7678:66;7671:5;7667:78;7656:89;;7602:149;;;:::o;7757:115::-;7842:23;7859:5;7842:23;:::i;:::-;7837:3;7830:36;7757:115;;:::o;7878:114::-;7945:6;7979:5;7973:12;7963:22;;7878:114;;;:::o;7998:184::-;8097:11;8131:6;8126:3;8119:19;8171:4;8166:3;8162:14;8147:29;;7998:184;;;;:::o;8188:132::-;8255:4;8278:3;8270:11;;8308:4;8303:3;8299:14;8291:22;;8188:132;;;:::o;8326:108::-;8403:24;8421:5;8403:24;:::i;:::-;8398:3;8391:37;8326:108;;:::o;8440:179::-;8509:10;8530:46;8572:3;8564:6;8530:46;:::i;:::-;8608:4;8603:3;8599:14;8585:28;;8440:179;;;;:::o;8625:113::-;8695:4;8727;8722:3;8718:14;8710:22;;8625:113;;;:::o;8774:732::-;8893:3;8922:54;8970:5;8922:54;:::i;:::-;8992:86;9071:6;9066:3;8992:86;:::i;:::-;8985:93;;9102:56;9152:5;9102:56;:::i;:::-;9181:7;9212:1;9197:284;9222:6;9219:1;9216:13;9197:284;;;9298:6;9292:13;9325:63;9384:3;9369:13;9325:63;:::i;:::-;9318:70;;9411:60;9464:6;9411:60;:::i;:::-;9401:70;;9257:224;9244:1;9241;9237:9;9232:14;;9197:284;;;9201:14;9497:3;9490:10;;8898:608;;;8774:732;;;;:::o;9512:1215::-;9861:4;9899:3;9888:9;9884:19;9876:27;;9913:69;9979:1;9968:9;9964:17;9955:6;9913:69;:::i;:::-;10029:9;10023:4;10019:20;10014:2;10003:9;9999:18;9992:48;10057:78;10130:4;10121:6;10057:78;:::i;:::-;10049:86;;10182:9;10176:4;10172:20;10167:2;10156:9;10152:18;10145:48;10210:78;10283:4;10274:6;10210:78;:::i;:::-;10202:86;;10298:72;10366:2;10355:9;10351:18;10342:6;10298:72;:::i;:::-;10380:73;10448:3;10437:9;10433:19;10424:6;10380:73;:::i;:::-;10463;10531:3;10520:9;10516:19;10507:6;10463:73;:::i;:::-;10584:9;10578:4;10574:20;10568:3;10557:9;10553:19;10546:49;10612:108;10715:4;10706:6;10612:108;:::i;:::-;10604:116;;9512:1215;;;;;;;;;;:::o;10733:474::-;10801:6;10809;10858:2;10846:9;10837:7;10833:23;10829:32;10826:119;;;10864:79;;:::i;:::-;10826:119;10984:1;11009:53;11054:7;11045:6;11034:9;11030:22;11009:53;:::i;:::-;10999:63;;10955:117;11111:2;11137:53;11182:7;11173:6;11162:9;11158:22;11137:53;:::i;:::-;11127:63;;11082:118;10733:474;;;;;:::o;11213:118::-;11284:22;11300:5;11284:22;:::i;:::-;11277:5;11274:33;11264:61;;11321:1;11318;11311:12;11264:61;11213:118;:::o;11337:135::-;11381:5;11419:6;11406:20;11397:29;;11435:31;11460:5;11435:31;:::i;:::-;11337:135;;;;:::o;11478:122::-;11551:24;11569:5;11551:24;:::i;:::-;11544:5;11541:35;11531:63;;11590:1;11587;11580:12;11531:63;11478:122;:::o;11606:139::-;11652:5;11690:6;11677:20;11668:29;;11706:33;11733:5;11706:33;:::i;:::-;11606:139;;;;:::o;11751:1199::-;11862:6;11870;11878;11886;11894;11902;11910;11959:3;11947:9;11938:7;11934:23;11930:33;11927:120;;;11966:79;;:::i;:::-;11927:120;12086:1;12111:53;12156:7;12147:6;12136:9;12132:22;12111:53;:::i;:::-;12101:63;;12057:117;12213:2;12239:53;12284:7;12275:6;12264:9;12260:22;12239:53;:::i;:::-;12229:63;;12184:118;12341:2;12367:53;12412:7;12403:6;12392:9;12388:22;12367:53;:::i;:::-;12357:63;;12312:118;12469:2;12495:53;12540:7;12531:6;12520:9;12516:22;12495:53;:::i;:::-;12485:63;;12440:118;12597:3;12624:51;12667:7;12658:6;12647:9;12643:22;12624:51;:::i;:::-;12614:61;;12568:117;12724:3;12751:53;12796:7;12787:6;12776:9;12772:22;12751:53;:::i;:::-;12741:63;;12695:119;12853:3;12880:53;12925:7;12916:6;12905:9;12901:22;12880:53;:::i;:::-;12870:63;;12824:119;11751:1199;;;;;;;;;;:::o;12956:607::-;13027:6;13035;13043;13092:2;13080:9;13071:7;13067:23;13063:32;13060:119;;;13098:79;;:::i;:::-;13060:119;13218:1;13243:53;13288:7;13279:6;13268:9;13264:22;13243:53;:::i;:::-;13233:63;;13189:117;13345:2;13371:50;13413:7;13404:6;13393:9;13389:22;13371:50;:::i;:::-;13361:60;;13316:115;13470:2;13496:50;13538:7;13529:6;13518:9;13514:22;13496:50;:::i;:::-;13486:60;;13441:115;12956:607;;;;;:::o;13569:180::-;13617:77;13614:1;13607:88;13714:4;13711:1;13704:15;13738:4;13735:1;13728:15;13755:320;13799:6;13836:1;13830:4;13826:12;13816:22;;13883:1;13877:4;13873:12;13904:18;13894:81;;13960:4;13952:6;13948:17;13938:27;;13894:81;14022:2;14014:6;14011:14;13991:18;13988:38;13985:84;;14041:18;;:::i;:::-;13985:84;13806:269;13755:320;;;:::o;14081:180::-;14129:77;14126:1;14119:88;14226:4;14223:1;14216:15;14250:4;14247:1;14240:15;14267:410;14307:7;14330:20;14348:1;14330:20;:::i;:::-;14325:25;;14364:20;14382:1;14364:20;:::i;:::-;14359:25;;14419:1;14416;14412:9;14441:30;14459:11;14441:30;:::i;:::-;14430:41;;14620:1;14611:7;14607:15;14604:1;14601:22;14581:1;14574:9;14554:83;14531:139;;14650:18;;:::i;:::-;14531:139;14315:362;14267:410;;;;:::o;14683:180::-;14731:77;14728:1;14721:88;14828:4;14825:1;14818:15;14852:4;14849:1;14842:15;14869:185;14909:1;14926:20;14944:1;14926:20;:::i;:::-;14921:25;;14960:20;14978:1;14960:20;:::i;:::-;14955:25;;14999:1;14989:35;;15004:18;;:::i;:::-;14989:35;15046:1;15043;15039:9;15034:14;;14869:185;;;;:::o;15060:180::-;15108:77;15105:1;15098:88;15205:4;15202:1;15195:15;15229:4;15226:1;15219:15;15246:147;15347:11;15384:3;15369:18;;15246:147;;;;:::o;15399:114::-;;:::o;15519:398::-;15678:3;15699:83;15780:1;15775:3;15699:83;:::i;:::-;15692:90;;15791:93;15880:3;15791:93;:::i;:::-;15909:1;15904:3;15900:11;15893:18;;15519:398;;;:::o;15923:379::-;16107:3;16129:147;16272:3;16129:147;:::i;:::-;16122:154;;16293:3;16286:10;;15923:379;;;:::o;16308:221::-;16448:34;16444:1;16436:6;16432:14;16425:58;16517:4;16512:2;16504:6;16500:15;16493:29;16308:221;:::o;16535:366::-;16677:3;16698:67;16762:2;16757:3;16698:67;:::i;:::-;16691:74;;16774:93;16863:3;16774:93;:::i;:::-;16892:2;16887:3;16883:12;16876:19;;16535:366;;;:::o;16907:419::-;17073:4;17111:2;17100:9;17096:18;17088:26;;17160:9;17154:4;17150:20;17146:1;17135:9;17131:17;17124:47;17188:131;17314:4;17188:131;:::i;:::-;17180:139;;16907:419;;;:::o;17332:143::-;17389:5;17420:6;17414:13;17405:22;;17436:33;17463:5;17436:33;:::i;:::-;17332:143;;;;:::o;17481:351::-;17551:6;17600:2;17588:9;17579:7;17575:23;17571:32;17568:119;;;17606:79;;:::i;:::-;17568:119;17726:1;17751:64;17807:7;17798:6;17787:9;17783:22;17751:64;:::i;:::-;17741:74;;17697:128;17481:351;;;;:::o;17838:332::-;17959:4;17997:2;17986:9;17982:18;17974:26;;18010:71;18078:1;18067:9;18063:17;18054:6;18010:71;:::i;:::-;18091:72;18159:2;18148:9;18144:18;18135:6;18091:72;:::i;:::-;17838:332;;;;;:::o;18176:137::-;18230:5;18261:6;18255:13;18246:22;;18277:30;18301:5;18277:30;:::i;:::-;18176:137;;;;:::o;18319:345::-;18386:6;18435:2;18423:9;18414:7;18410:23;18406:32;18403:119;;;18441:79;;:::i;:::-;18403:119;18561:1;18586:61;18639:7;18630:6;18619:9;18615:22;18586:61;:::i;:::-;18576:71;;18532:125;18319:345;;;;:::o;18670:775::-;18903:4;18941:3;18930:9;18926:19;18918:27;;18955:71;19023:1;19012:9;19008:17;18999:6;18955:71;:::i;:::-;19036:72;19104:2;19093:9;19089:18;19080:6;19036:72;:::i;:::-;19118;19186:2;19175:9;19171:18;19162:6;19118:72;:::i;:::-;19200;19268:2;19257:9;19253:18;19244:6;19200:72;:::i;:::-;19282:73;19350:3;19339:9;19335:19;19326:6;19282:73;:::i;:::-;19365;19433:3;19422:9;19418:19;19409:6;19365:73;:::i;:::-;18670:775;;;;;;;;;:::o;19451:332::-;19572:4;19610:2;19599:9;19595:18;19587:26;;19623:71;19691:1;19680:9;19676:17;19667:6;19623:71;:::i;:::-;19704:72;19772:2;19761:9;19757:18;19748:6;19704:72;:::i;:::-;19451:332;;;;;:::o;19789:442::-;19938:4;19976:2;19965:9;19961:18;19953:26;;19989:71;20057:1;20046:9;20042:17;20033:6;19989:71;:::i;:::-;20070:72;20138:2;20127:9;20123:18;20114:6;20070:72;:::i;:::-;20152;20220:2;20209:9;20205:18;20196:6;20152:72;:::i;:::-;19789:442;;;;;;:::o;20237:191::-;20277:3;20296:20;20314:1;20296:20;:::i;:::-;20291:25;;20330:20;20348:1;20330:20;:::i;:::-;20325:25;;20373:1;20370;20366:9;20359:16;;20394:3;20391:1;20388:10;20385:36;;;20401:18;;:::i;:::-;20385:36;20237:191;;;;:::o;20434:194::-;20474:4;20494:20;20512:1;20494:20;:::i;:::-;20489:25;;20528:20;20546:1;20528:20;:::i;:::-;20523:25;;20572:1;20569;20565:9;20557:17;;20596:1;20590:4;20587:11;20584:37;;;20601:18;;:::i;:::-;20584:37;20434:194;;;;:::o;20634:664::-;20839:4;20877:3;20866:9;20862:19;20854:27;;20891:71;20959:1;20948:9;20944:17;20935:6;20891:71;:::i;:::-;20972:72;21040:2;21029:9;21025:18;21016:6;20972:72;:::i;:::-;21054;21122:2;21111:9;21107:18;21098:6;21054:72;:::i;:::-;21136;21204:2;21193:9;21189:18;21180:6;21136:72;:::i;:::-;21218:73;21286:3;21275:9;21271:19;21262:6;21218:73;:::i;:::-;20634:664;;;;;;;;:::o;21304:545::-;21477:4;21515:3;21504:9;21500:19;21492:27;;21529:71;21597:1;21586:9;21582:17;21573:6;21529:71;:::i;:::-;21610:68;21674:2;21663:9;21659:18;21650:6;21610:68;:::i;:::-;21688:72;21756:2;21745:9;21741:18;21732:6;21688:72;:::i;:::-;21770;21838:2;21827:9;21823:18;21814:6;21770:72;:::i;:::-;21304:545;;;;;;;:::o;21855:180::-;21903:77;21900:1;21893:88;22000:4;21997:1;21990:15;22024:4;22021:1;22014:15
Swarm Source
ipfs://9445498aa666da2695d479dec544c428e0849687cc06138c2b124cb190908692
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.