ETH Price: $2,911.98 (-3.90%)
Gas: 2 Gwei

Cucumber Finance (CUCF)
 

Overview

TokenID

177

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Cucumbers404

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-02-13
*/

/*
https://t.me/CucumberFinanceETH
https://twitter.com/CucumberFinETH
*/

pragma solidity ^0.8.0;

// SPDX-License-Identifier: MIT

abstract contract Ownable {
    event OwnershipTransferred(address indexed user, address indexed newOwner);

    error Unauthorized();
    error InvalidOwner();

    address public owner;

    modifier onlyOwner() virtual {
        if (msg.sender != owner) revert Unauthorized();

        _;
    }

    constructor(address _owner) {
        if (_owner == address(0)) revert InvalidOwner();

        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    function transferOwnership(address _owner) public virtual onlyOwner {
        if (_owner == address(0)) revert InvalidOwner();

        owner = _owner;

        emit OwnershipTransferred(msg.sender, _owner);
    }

    function revokeOwnership() public virtual onlyOwner {
        owner = address(0);

        emit OwnershipTransferred(msg.sender, address(0));
    }
}

abstract contract ERC721Receiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721Receiver.onERC721Received.selector;
    }
}

abstract contract ERC404 is Ownable {
    // Events
    event ERC20Transfer(
        address indexed from,
        address indexed to,
        uint256 amount
    );
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 amount
    );
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed id
    );
    event ERC721Approval(
        address indexed owner,
        address indexed spender,
        uint256 indexed id
    );
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    // Errors
    error NotFound();
    error AlreadyExists();
    error InvalidRecipient();
    error InvalidSender();
    error UnsafeRecipient();

    // Metadata
    /// @dev Token name
    string public name;

    /// @dev Token symbol
    string public symbol;

    /// @dev Decimals for fractional representation
    uint8 public immutable decimals;

    /// @dev Total supply in fractionalized representation
    uint256 public immutable totalSupply;

    // @ERC404+ Array of burnt IDs
    uint256[] public _burnedTokenIds;

    /// @dev Current mint counter, monotonically increasing to ensure accurate ownership
    uint256 public minted;

    /// @dev Current mint counter, monotonically increasing to ensure accurate ownership
    uint256 public max_mint;

    // Mappings
    /// @dev Balance of user in fractional representation
    mapping(address => uint256) public balanceOf;

    /// @dev Allowance of user in fractional representation
    mapping(address => mapping(address => uint256)) public allowance;

    /// @dev Approval in native representaion
    mapping(uint256 => address) public getApproved;

    /// @dev Approval for all in native representation
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /// @dev Owner of id in native representation
    mapping(uint256 => address) internal _ownerOf;

    /// @dev Array of owned ids in native representation
    mapping(address => uint256[]) internal _owned;

    /// @dev Tracks indices for the _owned mapping
    mapping(uint256 => uint256) internal _ownedIndex;

    /// @dev Addresses whitelisted from minting / burning for gas savings (pairs, routers, etc)
    mapping(address => bool) public whitelist;



    // Constructor
    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals,
        uint256 _totalNativeSupply,
        address _owner
    ) Ownable(_owner) {
        name = _name;
        max_mint = _totalNativeSupply;
        symbol = _symbol;
        decimals = _decimals;
        totalSupply = _totalNativeSupply * (10 ** decimals);
        whitelist[msg.sender]=true;
    }

    /// @notice Initialization function to set pairs / etc
    ///         saving gas by avoiding mint / burn on unnecessary targets
    function setWhitelist(address target, bool state) public onlyOwner {
        whitelist[target] = state;
    }

    /// @notice Function to find owner of a given native token
    function ownerOf(uint256 id) public view virtual returns (address owner) {
        owner = _ownerOf[id];

        if (owner == address(0)) {
            revert NotFound();
        }
    }

    /// @notice tokenURI must be implemented by child contract
    function tokenURI(uint256 id) public view virtual returns (string memory);

    /// @notice Function for token approvals
    /// @dev This function assumes id / native if amount less than or equal to current max id
    function approve(
        address spender,
        uint256 amountOrId
    ) public virtual returns (bool) {
        if (amountOrId <= minted && amountOrId > 0) {
            address owner = _ownerOf[amountOrId];

            if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) {
                revert Unauthorized();
            }

            getApproved[amountOrId] = spender;

            emit Approval(owner, spender, amountOrId);
        } else {
            allowance[msg.sender][spender] = amountOrId;

            emit Approval(msg.sender, spender, amountOrId);
        }

        return true;
    }

    /// @notice Function native approvals
    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    /// @notice Function for mixed transfers
    /// @dev This function assumes id / native if amount less than or equal to current max id
    function transferFrom(
        address from,
        address to,
        uint256 amountOrId
    ) public virtual {
        if (amountOrId <= minted) {
            if (from != _ownerOf[amountOrId]) {
                revert InvalidSender();
            }

            if (to == address(0)) {
                revert InvalidRecipient();
            }

            if (
                msg.sender != from &&
                !isApprovedForAll[from][msg.sender] &&
                msg.sender != getApproved[amountOrId]
            ) {
                revert Unauthorized();
            }

            balanceOf[from] -= _getUnit();

            unchecked {
                balanceOf[to] += _getUnit();
            }

            _ownerOf[amountOrId] = to;
            delete getApproved[amountOrId];

            // update _owned for sender
            uint256 updatedId = _owned[from][_owned[from].length - 1];
            _owned[from][_ownedIndex[amountOrId]] = updatedId;
            // pop
            _owned[from].pop();
            // update index for the moved id
            _ownedIndex[updatedId] = _ownedIndex[amountOrId];
            // push token to to owned
            _owned[to].push(amountOrId);
            // update index for to owned
            _ownedIndex[amountOrId] = _owned[to].length - 1;

            emit Transfer(from, to, amountOrId);
            emit ERC20Transfer(from, to, _getUnit());
        } else {
            uint256 allowed = allowance[from][msg.sender];

            if (allowed != type(uint256).max)
                allowance[from][msg.sender] = allowed - amountOrId;

            _transfer(from, to, amountOrId);
        }
    }

    /// @notice Function for fractional transfers
    function transfer(
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        return _transfer(msg.sender, to, amount);
    }

    /// @notice Function for native transfers with contract support
    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        if (
            to.code.length != 0 &&
            ERC721Receiver(to).onERC721Received(msg.sender, from, id, "") !=
            ERC721Receiver.onERC721Received.selector
        ) {
            revert UnsafeRecipient();
        }
    }

    /// @notice Function for native transfers with contract support and callback data
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        if (
            to.code.length != 0 &&
            ERC721Receiver(to).onERC721Received(msg.sender, from, id, data) !=
            ERC721Receiver.onERC721Received.selector
        ) {
            revert UnsafeRecipient();
        }
    }

    /// @notice Internal function for fractional transfers
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal returns (bool) {
        uint256 unit = _getUnit();
        uint256 balanceBeforeSender = balanceOf[from];
        uint256 balanceBeforeReceiver = balanceOf[to];

        balanceOf[from] -= amount;

        unchecked {
            balanceOf[to] += amount;
        }

        // Skip burn for certain addresses to save gas
        if (!whitelist[from]) {
            uint256 tokens_to_burn = (balanceBeforeSender / unit) -
                (balanceOf[from] / unit);
            for (uint256 i = 0; i < tokens_to_burn; i++) {
                _burn(from);
            }
        }

        // Skip minting for certain addresses to save gas
        if (!whitelist[to]) {
            uint256 tokens_to_mint = (balanceOf[to] / unit) -
                (balanceBeforeReceiver / unit);
            for (uint256 i = 0; i < tokens_to_mint; i++) {
                _mint(to);
            }
        }

        emit ERC20Transfer(from, to, amount);
        return true;
    }

    // Internal utility logic
    function _getUnit() internal view returns (uint256) {
        return 10 ** decimals;
    }

    function _mint(address to) internal virtual {
        if (to == address(0)) {
            revert InvalidRecipient();
        }

        unchecked {
            minted++;
        }

        uint256 id = minted;

        if(minted > max_mint && _burnedTokenIds.length > 0){
            uint256 lastIndex = _burnedTokenIds.length - 1;
            id = _burnedTokenIds[lastIndex];
            _burnedTokenIds.pop();
        }

        if (_ownerOf[id] != address(0)) {
            revert AlreadyExists();
        }

        _ownerOf[id] = to;
        _owned[to].push(id);
        _ownedIndex[id] = _owned[to].length - 1;

        emit Transfer(address(0), to, id);
    }

    function _burn(address from) internal virtual {
        if (from == address(0)) {
            revert InvalidSender();
        }

        uint256 id = _owned[from][_owned[from].length - 1];
        _owned[from].pop();
        delete _ownedIndex[id];
        delete _ownerOf[id];
        delete getApproved[id];

        // push ID inside of burnt array
        _burnedTokenIds.push(id);

        emit Transfer(from, address(0), id);
    }

    function _setNameSymbol(
        string memory _name,
        string memory _symbol
    ) internal {
        name = _name;
        symbol = _symbol;
    }
}

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;
    }
}
/**
 * @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);
        }
    }
}

/**
 * @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));
    }
}

interface IUniswapV3Router {
    function factory() external view returns (address);
}

interface IUniswapV3Factory {
    function createPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external returns (address pool);
}

library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, 'SafeMath: addition overflow');

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, 'SafeMath: subtraction overflow');
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, 'SafeMath: multiplication overflow');

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, 'SafeMath: division by zero');
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, 'SafeMath: modulo by zero');
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }

    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x < y ? x : y;
    }

    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint256 y) internal pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }
}

interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the token decimals.
     */
    function decimals() external view returns (uint8);

    /**
     * @dev Returns the token symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the token name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the ERC token owner.
     */
    function getOwner() external view returns (address);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @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);
}

library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            'SafeERC20: approve from non-zero to non-zero allowance'
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(
            value,
            'SafeERC20: decreased allowance below zero'
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, 'SafeERC20: low-level call failed');
        if (returndata.length > 0) {
            // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed');
        }
    }
}

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            codehash := extcodehash(account)
        }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, 'Address: insufficient balance');

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{value: amount}('');
        require(success, 'Address: unable to send value, recipient may have reverted');
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, 'Address: low-level call failed');
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, 'Address: low-level call with value failed');
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, 'Address: insufficient balance for call');
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 weiValue,
        string memory errorMessage
    ) private returns (bytes memory) {
        require(isContract(target), 'Address: call to non-contract');

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{value: weiValue}(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

contract CucumberStaking is Ownable, ReentrancyGuard {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    // Info of each user.
    struct UserInfo {
        uint256 amount;     // How many LP tokens the user has provided.
        uint256 rewardDebt; // Reward debt. See explanation below.
    }

    // Info of each pool.
    struct PoolInfo {
        IERC20 lpToken;           // Address of LP token contract.
        uint256 lastRewardTimestamp;  // Last block number that Tokens distribution occurs.
        uint256 accTokensPerShare; // Accumulated Tokens per share, times 1e12. See below.
    }

    IERC20 public immutable stakingToken;
    IERC20 public immutable rewardToken;
    mapping (address => uint256) public holderUnlockTime;

    uint256 public totalStaked;
    uint256 public apr;
    uint256 public lockDuration;
    uint256 public exitPenaltyPerc;
    
    bool public canCompoundOrStakeMore;

    // Info of each pool.
    PoolInfo public poolInfo;
    // Info of each user that stakes LP tokens.
    mapping (address => UserInfo) public userInfo;

    event Deposit(address indexed user, uint256 amount);
    event Withdraw(address indexed user, uint256 amount);
    event Compound(address indexed user);
    event EmergencyWithdraw(address indexed user, uint256 amount);

    constructor(address _stakingToken, address _rewardToken, uint256 _apr, uint256 _lockDurationInDays, uint256 _exitPenaltyPerc, bool _canCompoundOrStakeMore, address _owner) Ownable(_owner){
        stakingToken = IERC20(_stakingToken);
        rewardToken = IERC20(_rewardToken);
        canCompoundOrStakeMore = _canCompoundOrStakeMore;

        apr = _apr;
        lockDuration = _lockDurationInDays * 1 days;
        exitPenaltyPerc = _exitPenaltyPerc;

        // staking pool
        poolInfo = (PoolInfo({
            lpToken: stakingToken,
            lastRewardTimestamp: 99999999999,
            accTokensPerShare: 0
        }));
    }

    function stopReward() external onlyOwner {
        updatePool();
        apr = 0;
    }

    function startReward() external onlyOwner {
        require(poolInfo.lastRewardTimestamp == 99999999999, "Can only start rewards once");
        poolInfo.lastRewardTimestamp = block.timestamp;
    }

    // View function to see pending Reward on frontend.
    function pendingReward(address _user) external view returns (uint256) {
        PoolInfo storage pool = poolInfo;
        UserInfo storage user = userInfo[_user];
        if(pool.lastRewardTimestamp == 99999999999){
            return 0;
        }
        uint256 accTokensPerShare = pool.accTokensPerShare;
        uint256 lpSupply = totalStaked;
        if (block.timestamp > pool.lastRewardTimestamp && lpSupply != 0) {
            uint256 tokenReward = calculateNewRewards();
            accTokensPerShare = accTokensPerShare.add(tokenReward.mul(1e12).div(lpSupply));
        }
        return user.amount.mul(accTokensPerShare).div(1e12).sub(user.rewardDebt);
    }

    // Update reward variables of the given pool to be up-to-date.
    function updatePool() internal {
        PoolInfo storage pool = poolInfo;
        if (block.timestamp <= pool.lastRewardTimestamp) {
            return;
        }
        uint256 lpSupply = totalStaked;
        if (lpSupply == 0) {
            pool.lastRewardTimestamp = block.timestamp;
            return;
        }
        uint256 tokenReward = calculateNewRewards();
        pool.accTokensPerShare = pool.accTokensPerShare.add(tokenReward.mul(1e12).div(lpSupply));
        pool.lastRewardTimestamp = block.timestamp;
    }

    // Stake primary tokens
    function deposit(uint256 _amount) external nonReentrant {
        if(holderUnlockTime[msg.sender] == 0){
            holderUnlockTime[msg.sender] = block.timestamp + lockDuration;
        }
        PoolInfo storage pool = poolInfo;
        UserInfo storage user = userInfo[msg.sender];

        if(!canCompoundOrStakeMore && _amount > 0){
            require(user.amount == 0, "Cannot stake more");
        }

        updatePool();
        if (user.amount > 0) {
            uint256 pending = user.amount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt);
            if(pending > 0) {
                require(pending <= rewardsRemaining(), "Cannot withdraw other people's staked tokens.  Contact an admin.");
                rewardToken.safeTransfer(address(msg.sender), pending);
            }
        }
        uint256 amountTransferred = 0;
        if(_amount > 0) {
            uint256 initialBalance = pool.lpToken.balanceOf(address(this));
            pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
            amountTransferred = pool.lpToken.balanceOf(address(this)) - initialBalance;
            user.amount = user.amount.add(amountTransferred);
            totalStaked += amountTransferred;
        }
        user.rewardDebt = user.amount.mul(pool.accTokensPerShare).div(1e12);

        emit Deposit(msg.sender, _amount);
    }

    function compound() external nonReentrant {
        require(canCompoundOrStakeMore, "Cannot compound");
        PoolInfo storage pool = poolInfo;
        UserInfo storage user = userInfo[msg.sender];

        updatePool();
        if (user.amount > 0) {
            uint256 pending = user.amount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt);
            if(pending > 0) {
                require(pending <= rewardsRemaining(), "Cannot withdraw other people's staked tokens.  Contact an admin.");
                user.amount += pending;
                totalStaked += pending;
            }
        }

        user.rewardDebt = user.amount.mul(pool.accTokensPerShare).div(1e12);
        emit Compound(msg.sender);
    }

    // Withdraw primary tokens from STAKING.

    function withdraw() external nonReentrant {

        require(holderUnlockTime[msg.sender] <= block.timestamp, "May not do normal withdraw early");
        
        PoolInfo storage pool = poolInfo;
        UserInfo storage user = userInfo[msg.sender];

        uint256 _amount = user.amount;
        updatePool();
        uint256 pending = user.amount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt);
        if(pending > 0){
            require(pending <= rewardsRemaining(), "Cannot withdraw other people's staked tokens.  Contact an admin.");
            rewardToken.safeTransfer(address(msg.sender), pending);
        }

        if(_amount > 0) {
            user.amount = 0;
            totalStaked -= _amount;
            pool.lpToken.safeTransfer(address(msg.sender), _amount);
        }

        user.rewardDebt = user.amount.mul(pool.accTokensPerShare).div(1e12);
        
        if(user.amount > 0){
            holderUnlockTime[msg.sender] = block.timestamp + lockDuration;
        } else {
            holderUnlockTime[msg.sender] = 0;
        }

        emit Withdraw(msg.sender, _amount);
    }

    // Withdraw without caring about rewards. EMERGENCY ONLY.
    function emergencyWithdraw() external nonReentrant {
        PoolInfo storage pool = poolInfo;
        UserInfo storage user = userInfo[msg.sender];
        uint256 _amount = user.amount;
        totalStaked -= _amount;
        // exit penalty for early unstakers, penalty held on contract as rewards.
        if(holderUnlockTime[msg.sender] >= block.timestamp){
            _amount -= _amount * exitPenaltyPerc / 100;
        }
        holderUnlockTime[msg.sender] = 0;
        pool.lpToken.safeTransfer(address(msg.sender), _amount);
        user.amount = 0;
        user.rewardDebt = 0;
        emit EmergencyWithdraw(msg.sender, _amount);
    }

    // Withdraw reward. EMERGENCY ONLY. This allows the owner to migrate rewards to a new staking pool since we are not minting new tokens.
    function emergencyRewardWithdraw(uint256 _amount) external onlyOwner {
        require(_amount <= rewardToken.balanceOf(address(this)) - totalStaked, 'not enough tokens to take out');
        rewardToken.safeTransfer(address(msg.sender), _amount);
    }

    function calculateNewRewards() public view returns (uint256) {
        PoolInfo storage pool = poolInfo;
        if(pool.lastRewardTimestamp > block.timestamp){
            return 0;
        }
        return (((block.timestamp - pool.lastRewardTimestamp) * totalStaked) * apr / 100 / 365 days);
    }

    function rewardsRemaining() public view returns (uint256){
        if(rewardToken == stakingToken){
            return rewardToken.balanceOf(address(this)) - totalStaked;
        } else {
            return rewardToken.balanceOf(address(this));
        }
    }

    function updateApr(uint256 newApr) external onlyOwner {
        require(newApr <= 10000, "APR must be below 10000%");
        updatePool();
        apr = newApr;
    }

    function updateExitPenalty(uint256 newPenaltyPerc) external onlyOwner {
        require(newPenaltyPerc <= 20, "May not set higher than 20%");
        exitPenaltyPerc = newPenaltyPerc;
    }

    function updateLockDuration(uint256 daysForLock) external onlyOwner {
        require(daysForLock <= 30, "Lock must be 30 days or less.");
        lockDuration = daysForLock * 1 days;
    }

    function updateCanCompoundOrStakeMore(bool compoundEnabled) external onlyOwner {
        canCompoundOrStakeMore = compoundEnabled;
    }
}

contract Cucumbers404 is ERC404 {

    IUniswapV3Router public immutable v3Router;
    address public pool;
    string public baseTokenURI;
    CucumberStaking public cucumberStakingContract;

    constructor(
        address _owner, uint256 _supply
    ) ERC404("Cucumber Finance", "CUCF", 18, _supply, _owner) {
        address wethContract;
        address _v3Router;
        // @dev assumes WETH pair
        if(block.chainid == 1){
            wethContract = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
            _v3Router = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
        } else if(block.chainid == 5){
            wethContract  = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6;
            _v3Router = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
        } else {
            revert("Chain not configured");
        }

        v3Router = IUniswapV3Router(_v3Router);
        pool = IUniswapV3Factory(v3Router.factory()).createPool(address(this), wethContract, 10000);
        cucumberStakingContract = new CucumberStaking(address(this), address(this), 5000, 3, 20, true, _owner);

        whitelist[address(v3Router)] = true;
        whitelist[pool] = true;
        whitelist[_owner] = true;
        whitelist[address(cucumberStakingContract)] = true;

        balanceOf[_owner] = _supply * _getUnit();
    }

    function setTokenURI(string memory _tokenURI) public onlyOwner {
        baseTokenURI = _tokenURI;
    }

    function tokenURI(uint256 id) public view override returns (string memory) {
        return string.concat(baseTokenURI, Strings.toString(id));
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_supply","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExists","type":"error"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeRecipient","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":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ERC721Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_burnedTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amountOrId","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cucumberStakingContract","outputs":[{"internalType":"contract CucumberStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"max_mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revokeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","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":"amountOrId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"v3Router","outputs":[{"internalType":"contract IUniswapV3Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60e06040523480156200001157600080fd5b5060405162007b9138038062007b918339818101604052810190620000379190620008b2565b6040518060400160405280601081526020017f437563756d6265722046696e616e6365000000000000000000000000000000008152506040518060400160405280600481526020017f43554346000000000000000000000000000000000000000000000000000000008152506012838580600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200010f576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3508460019080519060200190620001c39291906200074f565b50816005819055508360029080519060200190620001e39291906200074f565b508260ff1660808160ff1681525050608051600a62000203919062000a89565b8262000210919062000ada565b60a081815250506001600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505060008060014603620002b45773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2915073e592427a0aece92de3edee1f18e0157c0586156490506200032f565b60054603620002f15773b4fbf271143f4fbf7b91a5ded31805e42b2208d6915073e592427a0aece92de3edee1f18e0157c0586156490506200032e565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003259062000b9c565b60405180910390fd5b5b8073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff168152505060c05173ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003d7919062000bbe565b73ffffffffffffffffffffffffffffffffffffffff1663a167129530846127106040518463ffffffff1660e01b8152600401620004179392919062000c5d565b6020604051808303816000875af115801562000437573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200045d919062000bbe565b600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550303061138860036014600189604051620004b790620007e0565b620004c9979695949392919062000d80565b604051809103906000f080158015620004e6573d6000803e3d6000fd5b50601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600d600060c05173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600d6000600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600d6000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620006dd6200073760201b60201c565b83620006ea919062000ada565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050505062000e61565b6000608051600a6200074a919062000a89565b905090565b8280546200075d9062000e2c565b90600052602060002090601f016020900481019282620007815760008555620007cd565b82601f106200079c57805160ff1916838001178555620007cd565b82800160010185558215620007cd579182015b82811115620007cc578251825591602001919060010190620007af565b5b509050620007dc9190620007ee565b5090565b613742806200444f83390190565b5b8082111562000809576000816000905550600101620007ef565b5090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200083f8262000812565b9050919050565b620008518162000832565b81146200085d57600080fd5b50565b600081519050620008718162000846565b92915050565b6000819050919050565b6200088c8162000877565b81146200089857600080fd5b50565b600081519050620008ac8162000881565b92915050565b60008060408385031215620008cc57620008cb6200080d565b5b6000620008dc8582860162000860565b9250506020620008ef858286016200089b565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b600185111562000987578086048111156200095f576200095e620008f9565b5b60018516156200096f5780820291505b80810290506200097f8562000928565b94506200093f565b94509492505050565b600082620009a2576001905062000a75565b81620009b2576000905062000a75565b8160018114620009cb5760028114620009d65762000a0c565b600191505062000a75565b60ff841115620009eb57620009ea620008f9565b5b8360020a91508482111562000a055762000a04620008f9565b5b5062000a75565b5060208310610133831016604e8410600b841016171562000a465782820a90508381111562000a405762000a3f620008f9565b5b62000a75565b62000a55848484600162000935565b9250905081840481111562000a6f5762000a6e620008f9565b5b81810290505b9392505050565b600060ff82169050919050565b600062000a968262000877565b915062000aa38362000a7c565b925062000ad27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000990565b905092915050565b600062000ae78262000877565b915062000af48362000877565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000b305762000b2f620008f9565b5b828202905092915050565b600082825260208201905092915050565b7f436861696e206e6f7420636f6e66696775726564000000000000000000000000600082015250565b600062000b8460148362000b3b565b915062000b918262000b4c565b602082019050919050565b6000602082019050818103600083015262000bb78162000b75565b9050919050565b60006020828403121562000bd75762000bd66200080d565b5b600062000be78482850162000860565b91505092915050565b62000bfb8162000832565b82525050565b6000819050919050565b600062ffffff82169050919050565b6000819050919050565b600062000c4562000c3f62000c398462000c01565b62000c1a565b62000c0b565b9050919050565b62000c578162000c24565b82525050565b600060608201905062000c74600083018662000bf0565b62000c83602083018562000bf0565b62000c92604083018462000c4c565b949350505050565b6000819050919050565b600062000cc562000cbf62000cb98462000c9a565b62000c1a565b62000877565b9050919050565b62000cd78162000ca4565b82525050565b6000819050919050565b600062000d0862000d0262000cfc8462000cdd565b62000c1a565b62000877565b9050919050565b62000d1a8162000ce7565b82525050565b6000819050919050565b600062000d4b62000d4562000d3f8462000d20565b62000c1a565b62000877565b9050919050565b62000d5d8162000d2a565b82525050565b60008115159050919050565b62000d7a8162000d63565b82525050565b600060e08201905062000d97600083018a62000bf0565b62000da6602083018962000bf0565b62000db5604083018862000ccc565b62000dc4606083018762000d0f565b62000dd3608083018662000d52565b62000de260a083018562000d6f565b62000df160c083018462000bf0565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062000e4557607f821691505b60208210810362000e5b5762000e5a62000dfd565b5b50919050565b60805160a05160c0516135b762000e986000396000610988015260006109d20152600081816113500152611cf401526135b76000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80636352211e11610104578063b88d4fde116100a2578063dd62ed3e11610071578063dd62ed3e14610534578063e0df5b6f14610564578063e985e9c514610580578063f2fde38b146105b0576101cf565b8063b88d4fde146104ac578063c87b56dd146104c8578063d547cfb7146104f8578063d7c64e7f14610516576101cf565b806395d89b41116100de57806395d89b41146104125780639b19251a14610430578063a22cb46514610460578063a9059cbb1461047c576101cf565b80636352211e1461039457806370a08231146103c45780638da5cb5b146103f4576101cf565b80632b9689581161017157806342842e0e1161014b57806342842e0e1461030e5780634f02c4201461032a57806353d6fd591461034857806356bb8cb614610364576101cf565b80632b968958146102c8578063313ce567146102d25780633cd60e06146102f0576101cf565b80630dc91306116101ad5780630dc913061461025257806316f0115b1461027057806318160ddd1461028e57806323b872dd146102ac576101cf565b806306fdde03146101d4578063081812fc146101f2578063095ea7b314610222575b600080fd5b6101dc6105cc565b6040516101e99190612985565b60405180910390f35b61020c600480360381019061020791906129f1565b61065a565b6040516102199190612a5f565b60405180910390f35b61023c60048036038101906102379190612aa6565b61068d565b6040516102499190612b01565b60405180910390f35b61025a610986565b6040516102679190612b7b565b60405180910390f35b6102786109aa565b6040516102859190612a5f565b60405180910390f35b6102966109d0565b6040516102a39190612ba5565b60405180910390f35b6102c660048036038101906102c19190612bc0565b6109f4565b005b6102d061122b565b005b6102da61134e565b6040516102e79190612c2f565b60405180910390f35b6102f8611372565b6040516103059190612c6b565b60405180910390f35b61032860048036038101906103239190612bc0565b611398565b005b6103326114cb565b60405161033f9190612ba5565b60405180910390f35b610362600480360381019061035d9190612cb2565b6114d1565b005b61037e600480360381019061037991906129f1565b6115b1565b60405161038b9190612ba5565b60405180910390f35b6103ae60048036038101906103a991906129f1565b6115d5565b6040516103bb9190612a5f565b60405180910390f35b6103de60048036038101906103d99190612cf2565b611678565b6040516103eb9190612ba5565b60405180910390f35b6103fc611690565b6040516104099190612a5f565b60405180910390f35b61041a6116b4565b6040516104279190612985565b60405180910390f35b61044a60048036038101906104459190612cf2565b611742565b6040516104579190612b01565b60405180910390f35b61047a60048036038101906104759190612cb2565b611762565b005b61049660048036038101906104919190612aa6565b61185f565b6040516104a39190612b01565b60405180910390f35b6104c660048036038101906104c19190612d84565b611874565b005b6104e260048036038101906104dd91906129f1565b6119ad565b6040516104ef9190612985565b60405180910390f35b6105006119e1565b60405161050d9190612985565b60405180910390f35b61051e611a6f565b60405161052b9190612ba5565b60405180910390f35b61054e60048036038101906105499190612e0c565b611a75565b60405161055b9190612ba5565b60405180910390f35b61057e60048036038101906105799190612f7c565b611a9a565b005b61059a60048036038101906105959190612e0c565b611b39565b6040516105a79190612b01565b60405180910390f35b6105ca60048036038101906105c59190612cf2565b611b68565b005b600180546105d990612ff4565b80601f016020809104026020016040519081016040528092919081815260200182805461060590612ff4565b80156106525780601f1061062757610100808354040283529160200191610652565b820191906000526020600020905b81548152906001019060200180831161063557829003601f168201915b505050505081565b60086020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060045482111580156106a15750600082115b15610895576000600a600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156107a15750600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b156107d8576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836008600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516108879190612ba5565b60405180910390a35061097c565b81600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109739190612ba5565b60405180910390a35b6001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60045481116110e357600a600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610a95576040517fddb5de5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610afb576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610bbe5750600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b8015610c2957506008600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610c60576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c68611cf0565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610cb69190613054565b92505081905550610cc5611cf0565b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600a600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506008600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050610e299190613054565b81548110610e3a57610e39613088565b5b9060005260206000200154905080600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600c60008581526020019081526020016000205481548110610eac57610eab613088565b5b9060005260206000200181905550600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480610f0957610f086130b7565b5b60019003818190600052602060002001600090559055600c600083815260200190815260200160002054600c600083815260200190815260200160002081905550600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208290806001815401808255809150506001900390600052602060002001600090919091909150556001600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050610fff9190613054565b600c600084815260200190815260200160002081905550818373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fe59fdd36d0d223c0c7d996db7ad796880f45e1936cb0bb7ac102e7082e0314876110c8611cf0565b6040516110d59190612ba5565b60405180910390a350611226565b6000600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146112185781816111979190613054565b600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b611223848484611d24565b50505b505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112b0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6113a38383836109f4565b60008273ffffffffffffffffffffffffffffffffffffffff163b1415801561148f575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168273ffffffffffffffffffffffffffffffffffffffff1663150b7a023386856040518463ffffffff1660e01b815260040161142a9392919061311d565b6020604051808303816000875af1158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d91906131bf565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614155b156114c6576040517f3da6393100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60045481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611556576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600381815481106115c157600080fd5b906000526020600020016000915090505481565b6000600a600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611673576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60066020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600280546116c190612ff4565b80601f01602080910402602001604051908101604052809291908181526020018280546116ed90612ff4565b801561173a5780601f1061170f5761010080835404028352916020019161173a565b820191906000526020600020905b81548152906001019060200180831161171d57829003601f168201915b505050505081565b600d6020528060005260406000206000915054906101000a900460ff1681565b80600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516118539190612b01565b60405180910390a35050565b600061186c338484611d24565b905092915050565b61187f8585856109f4565b60008473ffffffffffffffffffffffffffffffffffffffff163b1415801561196f575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff1663150b7a0233888787876040518663ffffffff1660e01b815260040161190a959493929190613219565b6020604051808303816000875af1158015611929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194d91906131bf565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614155b156119a6576040517f3da6393100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6060600f6119ba8361208f565b6040516020016119cb929190613337565b6040516020818303038152906040529050919050565b600f80546119ee90612ff4565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1a90612ff4565b8015611a675780601f10611a3c57610100808354040283529160200191611a67565b820191906000526020600020905b815481529060010190602001808311611a4a57829003601f168201915b505050505081565b60055481565b6007602052816000526040600020602052806000526040600020600091509150505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b1f576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600f9080519060200190611b35929190612849565b5050565b60096020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bed576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611c53576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b60007f0000000000000000000000000000000000000000000000000000000000000000600a611d1f919061348e565b905090565b600080611d2f611cf0565b90506000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905084600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611e089190613054565b9250508190555084600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611f3c57600083600660008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611efa9190613508565b8484611f069190613508565b611f109190613054565b905060005b81811015611f3957611f268961215d565b8080611f3190613539565b915050611f15565b50505b600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661201c5760008382611f9b9190613508565b84600660008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611fe69190613508565b611ff09190613054565b905060005b8181101561201957612006886123e2565b808061201190613539565b915050611ff5565b50505b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fe59fdd36d0d223c0c7d996db7ad796880f45e1936cb0bb7ac102e7082e031487876040516120799190612ba5565b60405180910390a3600193505050509392505050565b60606000600161209e846126f6565b01905060008167ffffffffffffffff8111156120bd576120bc612e51565b5b6040519080825280601f01601f1916602001820160405280156120ef5781602001600182028036833780820191505090505b509050600082602001820190505b600115612152578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612146576121456134d9565b5b049450600085036120fd575b819350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121c3576040517fddb5de5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506122539190613054565b8154811061226457612263613088565b5b90600052602060002001549050600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806122c0576122bf6130b7565b5b60019003818190600052602060002001600090559055600c600082815260200190815260200160002060009055600a600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600381908060018154018082558091505060019003906000526020600020016000909190919091505580600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612448576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004600081548092919060010191905055506000600454905060055460045411801561247957506000600380549050115b156124df57600060016003805490506124929190613054565b9050600381815481106124a8576124a7613088565b5b9060005260206000200154915060038054806124c7576124c66130b7565b5b60019003818190600052602060002001600090559055505b600073ffffffffffffffffffffffffffffffffffffffff16600a600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612578576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600a600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150556001600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061267f9190613054565b600c600083815260200190815260200160002081905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612754577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161274a576127496134d9565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612791576d04ee2d6d415b85acef81000000008381612787576127866134d9565b5b0492506020810190505b662386f26fc1000083106127c057662386f26fc1000083816127b6576127b56134d9565b5b0492506010810190505b6305f5e10083106127e9576305f5e10083816127df576127de6134d9565b5b0492506008810190505b612710831061280e576127108381612804576128036134d9565b5b0492506004810190505b606483106128315760648381612827576128266134d9565b5b0492506002810190505b600a8310612840576001810190505b80915050919050565b82805461285590612ff4565b90600052602060002090601f01602090048101928261287757600085556128be565b82601f1061289057805160ff19168380011785556128be565b828001600101855582156128be579182015b828111156128bd5782518255916020019190600101906128a2565b5b5090506128cb91906128cf565b5090565b5b808211156128e85760008160009055506001016128d0565b5090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561292657808201518184015260208101905061290b565b83811115612935576000848401525b50505050565b6000601f19601f8301169050919050565b6000612957826128ec565b61296181856128f7565b9350612971818560208601612908565b61297a8161293b565b840191505092915050565b6000602082019050818103600083015261299f818461294c565b905092915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6129ce816129bb565b81146129d957600080fd5b50565b6000813590506129eb816129c5565b92915050565b600060208284031215612a0757612a066129b1565b5b6000612a15848285016129dc565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612a4982612a1e565b9050919050565b612a5981612a3e565b82525050565b6000602082019050612a746000830184612a50565b92915050565b612a8381612a3e565b8114612a8e57600080fd5b50565b600081359050612aa081612a7a565b92915050565b60008060408385031215612abd57612abc6129b1565b5b6000612acb85828601612a91565b9250506020612adc858286016129dc565b9150509250929050565b60008115159050919050565b612afb81612ae6565b82525050565b6000602082019050612b166000830184612af2565b92915050565b6000819050919050565b6000612b41612b3c612b3784612a1e565b612b1c565b612a1e565b9050919050565b6000612b5382612b26565b9050919050565b6000612b6582612b48565b9050919050565b612b7581612b5a565b82525050565b6000602082019050612b906000830184612b6c565b92915050565b612b9f816129bb565b82525050565b6000602082019050612bba6000830184612b96565b92915050565b600080600060608486031215612bd957612bd86129b1565b5b6000612be786828701612a91565b9350506020612bf886828701612a91565b9250506040612c09868287016129dc565b9150509250925092565b600060ff82169050919050565b612c2981612c13565b82525050565b6000602082019050612c446000830184612c20565b92915050565b6000612c5582612b48565b9050919050565b612c6581612c4a565b82525050565b6000602082019050612c806000830184612c5c565b92915050565b612c8f81612ae6565b8114612c9a57600080fd5b50565b600081359050612cac81612c86565b92915050565b60008060408385031215612cc957612cc86129b1565b5b6000612cd785828601612a91565b9250506020612ce885828601612c9d565b9150509250929050565b600060208284031215612d0857612d076129b1565b5b6000612d1684828501612a91565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612d4457612d43612d1f565b5b8235905067ffffffffffffffff811115612d6157612d60612d24565b5b602083019150836001820283011115612d7d57612d7c612d29565b5b9250929050565b600080600080600060808688031215612da057612d9f6129b1565b5b6000612dae88828901612a91565b9550506020612dbf88828901612a91565b9450506040612dd0888289016129dc565b935050606086013567ffffffffffffffff811115612df157612df06129b6565b5b612dfd88828901612d2e565b92509250509295509295909350565b60008060408385031215612e2357612e226129b1565b5b6000612e3185828601612a91565b9250506020612e4285828601612a91565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612e898261293b565b810181811067ffffffffffffffff82111715612ea857612ea7612e51565b5b80604052505050565b6000612ebb6129a7565b9050612ec78282612e80565b919050565b600067ffffffffffffffff821115612ee757612ee6612e51565b5b612ef08261293b565b9050602081019050919050565b82818337600083830152505050565b6000612f1f612f1a84612ecc565b612eb1565b905082815260208101848484011115612f3b57612f3a612e4c565b5b612f46848285612efd565b509392505050565b600082601f830112612f6357612f62612d1f565b5b8135612f73848260208601612f0c565b91505092915050565b600060208284031215612f9257612f916129b1565b5b600082013567ffffffffffffffff811115612fb057612faf6129b6565b5b612fbc84828501612f4e565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061300c57607f821691505b60208210810361301f5761301e612fc5565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061305f826129bb565b915061306a836129bb565b92508282101561307d5761307c613025565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082825260208201905092915050565b50565b60006131076000836130e6565b9150613112826130f7565b600082019050919050565b60006080820190506131326000830186612a50565b61313f6020830185612a50565b61314c6040830184612b96565b818103606083015261315d816130fa565b9050949350505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61319c81613167565b81146131a757600080fd5b50565b6000815190506131b981613193565b92915050565b6000602082840312156131d5576131d46129b1565b5b60006131e3848285016131aa565b91505092915050565b60006131f883856130e6565b9350613205838584612efd565b61320e8361293b565b840190509392505050565b600060808201905061322e6000830188612a50565b61323b6020830187612a50565b6132486040830186612b96565b818103606083015261325b8184866131ec565b90509695505050505050565b600081905092915050565b60008190508160005260206000209050919050565b6000815461329481612ff4565b61329e8186613267565b945060018216600081146132b957600181146132ca576132fd565b60ff198316865281860193506132fd565b6132d385613272565b60005b838110156132f5578154818901526001820191506020810190506132d6565b838801955050505b50505092915050565b6000613311826128ec565b61331b8185613267565b935061332b818560208601612908565b80840191505092915050565b60006133438285613287565b915061334f8284613306565b91508190509392505050565b60008160011c9050919050565b6000808291508390505b60018511156133b25780860481111561338e5761338d613025565b5b600185161561339d5780820291505b80810290506133ab8561335b565b9450613372565b94509492505050565b6000826133cb5760019050613487565b816133d95760009050613487565b81600181146133ef57600281146133f957613428565b6001915050613487565b60ff84111561340b5761340a613025565b5b8360020a91508482111561342257613421613025565b5b50613487565b5060208310610133831016604e8410600b841016171561345d5782820a90508381111561345857613457613025565b5b613487565b61346a8484846001613368565b9250905081840481111561348157613480613025565b5b81810290505b9392505050565b6000613499826129bb565b91506134a483612c13565b92506134d17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846133bb565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613513826129bb565b915061351e836129bb565b92508261352e5761352d6134d9565b5b828204905092915050565b6000613544826129bb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361357657613575613025565b5b60018201905091905056fea26469706673582212201180cd6399806b592955f99517cb4c5263046852e76d3b757a019ad7e18f358364736f6c634300080e003360c06040523480156200001157600080fd5b506040516200374238038062003742833981810160405281019062000037919062000371565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200009f576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600180819055508673ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508573ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505081600760006101000a81548160ff021916908315150217905550846004819055506201518084620001dc919062000453565b60058190555082600681905550604051806060016040528060805173ffffffffffffffffffffffffffffffffffffffff16815260200164174876e7ff81526020016000815250600860008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101556040820151816002015590505050505050505050620004b4565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620002c18262000294565b9050919050565b620002d381620002b4565b8114620002df57600080fd5b50565b600081519050620002f381620002c8565b92915050565b6000819050919050565b6200030e81620002f9565b81146200031a57600080fd5b50565b6000815190506200032e8162000303565b92915050565b60008115159050919050565b6200034b8162000334565b81146200035757600080fd5b50565b6000815190506200036b8162000340565b92915050565b600080600080600080600060e0888a0312156200039357620003926200028f565b5b6000620003a38a828b01620002e2565b9750506020620003b68a828b01620002e2565b9650506040620003c98a828b016200031d565b9550506060620003dc8a828b016200031d565b9450506080620003ef8a828b016200031d565b93505060a0620004028a828b016200035a565b92505060c0620004158a828b01620002e2565b91505092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200046082620002f9565b91506200046d83620002f9565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615620004a957620004a862000424565b5b828202905092915050565b60805160a0516132306200051260003960008181610704015281816107ef01528181610a0501528181610d9101528181610dd001528181610e7b015281816114640152611f37015260008181610c570152610d5a01526132306000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806380dc0672116100f9578063b6b55f2511610097578063f2fde38b11610071578063f2fde38b14610417578063f40f0f5214610433578063f69e204614610463578063f7c618c11461046d576101a9565b8063b6b55f25146103d5578063d477edf4146103f1578063db2e21bc1461040d576101a9565b80638da5cb5b116100d35780638da5cb5b1461034d5780638e0b01981461036b578063999e2f7514610387578063a913a5f7146103a5576101a9565b806380dc067214610309578063817b1cd2146103135780638552bf9014610331576101a9565b806357ded9c91161016657806372f702f31161014057806372f702f3146102a5578063746c8ae1146102c357806378c196f3146102cd5780637b280def146102eb576101a9565b806357ded9c9146102495780635a2f3d091461026757806368365d0314610287576101a9565b806304554443146101ae5780630698260f146101cc5780631959a002146101e85780632b968958146102195780633279beab146102235780633ccfd60b1461023f575b600080fd5b6101b661048b565b6040516101c39190612599565b60405180910390f35b6101e660048036038101906101e191906125f1565b610491565b005b61020260048036038101906101fd919061267c565b610533565b6040516102109291906126a9565b60405180910390f35b610221610557565b005b61023d600480360381019061023891906126fe565b61067a565b005b610247610836565b005b610251610c04565b60405161025e9190612599565b60405180910390f35b61026f610c0a565b60405161027e9392919061278a565b60405180910390f35b61028f610c42565b60405161029c91906127d0565b60405180910390f35b6102ad610c55565b6040516102ba91906127eb565b60405180910390f35b6102cb610c79565b005b6102d5610d56565b6040516102e29190612599565b60405180910390f35b6102f3610f19565b6040516103009190612599565b60405180910390f35b610311610f1f565b005b61031b610fb6565b6040516103289190612599565b60405180910390f35b61034b600480360381019061034691906126fe565b610fbc565b005b610355611098565b6040516103629190612815565b60405180910390f35b610385600480360381019061038091906126fe565b6110bc565b005b61038f61118f565b60405161039c9190612599565b60405180910390f35b6103bf60048036038101906103ba919061267c565b6111f8565b6040516103cc9190612599565b60405180910390f35b6103ef60048036038101906103ea91906126fe565b611210565b005b61040b600480360381019061040691906126fe565b611722565b005b610415611803565b005b610431600480360381019061042c919061267c565b611a2b565b005b61044d6004803603810190610448919061267c565b611bb3565b60405161045a9190612599565b60405180910390f35b61046b611cdd565b005b610475611f35565b60405161048291906127eb565b60405180910390f35b60055481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610516576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006101000a81548160ff02191690831515021790555050565b600b6020528060005260406000206000915090508060000154908060010154905082565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105dc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106ff576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161075b9190612815565b602060405180830381865afa158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079c9190612845565b6107a691906128a1565b8111156107e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107df90612932565b60405180910390fd5b61083333827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16611f599092919063ffffffff16565b50565b60026001540361087b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108729061299e565b60405180910390fd5b600260018190555042600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115610905576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fc90612a0a565b60405180910390fd5b6000600890506000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905061095f611fdf565b60006109a9836001015461099b64e8d4a5100061098d8860020154886000015461207890919063ffffffff16565b6120f290919063ffffffff16565b61213c90919063ffffffff16565b90506000811115610a4a576109bc610d56565b8111156109fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f590612a9c565b60405180910390fd5b610a4933827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16611f599092919063ffffffff16565b5b6000821115610ac657600083600001819055508160036000828254610a6f91906128a1565b92505081905550610ac533838660000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611f599092919063ffffffff16565b5b610af864e8d4a51000610aea8660020154866000015461207890919063ffffffff16565b6120f290919063ffffffff16565b8360010181905550600083600001541115610b635760055442610b1b9190612abc565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610ba9565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b3373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436483604051610bef9190612599565b60405180910390a25050505060018081905550565b60045481565b60088060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154905083565b600760009054906101000a900460ff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cfe576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b64174876e7ff60086001015414610d4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d4190612b5e565b60405180910390fd5b42600860010181905550565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1603610e79576003547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610e279190612815565b602060405180830381865afa158015610e44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e689190612845565b610e7291906128a1565b9050610f16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ed29190612815565b602060405180830381865afa158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f139190612845565b90505b90565b60065481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fa4576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fac611fdf565b6000600481905550565b60035481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611041576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612710811115611086576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107d90612bca565b60405180910390fd5b61108e611fdf565b8060048190555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611141576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6014811115611185576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117c90612c36565b60405180910390fd5b8060068190555050565b6000806008905042816001015411156111ac5760009150506111f5565b6301e1338060646004546003548460010154426111c991906128a1565b6111d39190612c56565b6111dd9190612c56565b6111e79190612cdf565b6111f19190612cdf565b9150505b90565b60026020528060005260406000206000915090505481565b600260015403611255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124c9061299e565b60405180910390fd5b60026001819055506000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036112f657600554426112b29190612abc565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6000600890506000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600760009054906101000a900460ff1615801561135c5750600083115b156113a95760008160000154146113a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161139f90612d5c565b60405180910390fd5b5b6113b1611fdf565b6000816000015411156114ab57600061140882600101546113fa64e8d4a510006113ec8760020154876000015461207890919063ffffffff16565b6120f290919063ffffffff16565b61213c90919063ffffffff16565b905060008111156114a95761141b610d56565b81111561145d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145490612a9c565b60405180910390fd5b6114a833827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16611f599092919063ffffffff16565b5b505b60008084111561168d5760008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016115149190612815565b602060405180830381865afa158015611531573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115559190612845565b90506115a83330878760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612186909392919063ffffffff16565b808460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016116069190612815565b602060405180830381865afa158015611623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116479190612845565b61165191906128a1565b915061166a82846000015461220f90919063ffffffff16565b836000018190555081600360008282546116849190612abc565b92505081905550505b6116bf64e8d4a510006116b18560020154856000015461207890919063ffffffff16565b6120f290919063ffffffff16565b82600101819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c8560405161170d9190612599565b60405180910390a25050506001808190555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117a7576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601e8111156117eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e290612dc8565b60405180910390fd5b62015180816117fa9190612c56565b60058190555050565b600260015403611848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161183f9061299e565b60405180910390fd5b60026001819055506000600890506000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905080600360008282546118b491906128a1565b9250508190555042600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410611929576064600654826119119190612c56565b61191b9190612cdf565b8161192691906128a1565b90505b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506119bd33828560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611f599092919063ffffffff16565b60008260000181905550600082600101819055503373ffffffffffffffffffffffffffffffffffffffff167f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd969582604051611a179190612599565b60405180910390a250505060018081905550565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611ab0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b16576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080600890506000600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905064174876e7ff826001015403611c1857600092505050611cd8565b60008260020154905060006003549050836001015442118015611c3c575060008114155b15611c8d576000611c4b61118f565b9050611c89611c7a83611c6c64e8d4a510008561207890919063ffffffff16565b6120f290919063ffffffff16565b8461220f90919063ffffffff16565b9250505b611cd18360010154611cc364e8d4a51000611cb586886000015461207890919063ffffffff16565b6120f290919063ffffffff16565b61213c90919063ffffffff16565b9450505050505b919050565b600260015403611d22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d199061299e565b60405180910390fd5b6002600181905550600760009054906101000a900460ff16611d79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7090612e34565b60405180910390fd5b6000600890506000600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611dca611fdf565b600081600001541115611ead576000611e218260010154611e1364e8d4a51000611e058760020154876000015461207890919063ffffffff16565b6120f290919063ffffffff16565b61213c90919063ffffffff16565b90506000811115611eab57611e34610d56565b811115611e76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6d90612a9c565b60405180910390fd5b80826000016000828254611e8a9190612abc565b925050819055508060036000828254611ea39190612abc565b925050819055505b505b611edf64e8d4a51000611ed18460020154846000015461207890919063ffffffff16565b6120f290919063ffffffff16565b81600101819055503373ffffffffffffffffffffffffffffffffffffffff167fda323bd96658b18a6ce813e824305dc61760462bad6aaf52c65aebb8c8c9faa160405160405180910390a2505060018081905550565b7f000000000000000000000000000000000000000000000000000000000000000081565b611fda8363a9059cbb60e01b8484604051602401611f78929190612e54565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061226d565b505050565b60006008905080600101544211611ff65750612076565b6000600354905060008103612015574282600101819055505050612076565b600061201f61118f565b905061206161204e8361204064e8d4a510008561207890919063ffffffff16565b6120f290919063ffffffff16565b846002015461220f90919063ffffffff16565b83600201819055504283600101819055505050505b565b600080830361208a57600090506120ec565b600082846120989190612c56565b90508284826120a79190612cdf565b146120e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120de90612eef565b60405180910390fd5b809150505b92915050565b600061213483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612334565b905092915050565b600061217e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612397565b905092915050565b612209846323b872dd60e01b8585856040516024016121a793929190612f0f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061226d565b50505050565b600080828461221e9190612abc565b905083811015612263576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225a90612f92565b60405180910390fd5b8091505092915050565b60006122cf826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123fb9092919063ffffffff16565b905060008151111561232f57808060200190518101906122ef9190612fc7565b61232e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232590613066565b60405180910390fd5b5b505050565b6000808311829061237b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612372919061310e565b60405180910390fd5b506000838561238a9190612cdf565b9050809150509392505050565b60008383111582906123df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123d6919061310e565b60405180910390fd5b50600083856123ee91906128a1565b9050809150509392505050565b606061240a8484600085612413565b90509392505050565b606061241e85612535565b61245d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124549061317c565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161248691906131e3565b60006040518083038185875af1925050503d80600081146124c3576040519150601f19603f3d011682016040523d82523d6000602084013e6124c8565b606091505b509150915081156124dd57809250505061252d565b6000815111156124f05780518082602001fd5b836040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612524919061310e565b60405180910390fd5b949350505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561257757506000801b8214155b92505050919050565b6000819050919050565b61259381612580565b82525050565b60006020820190506125ae600083018461258a565b92915050565b600080fd5b60008115159050919050565b6125ce816125b9565b81146125d957600080fd5b50565b6000813590506125eb816125c5565b92915050565b600060208284031215612607576126066125b4565b5b6000612615848285016125dc565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006126498261261e565b9050919050565b6126598161263e565b811461266457600080fd5b50565b60008135905061267681612650565b92915050565b600060208284031215612692576126916125b4565b5b60006126a084828501612667565b91505092915050565b60006040820190506126be600083018561258a565b6126cb602083018461258a565b9392505050565b6126db81612580565b81146126e657600080fd5b50565b6000813590506126f8816126d2565b92915050565b600060208284031215612714576127136125b4565b5b6000612722848285016126e9565b91505092915050565b6000819050919050565b600061275061274b6127468461261e565b61272b565b61261e565b9050919050565b600061276282612735565b9050919050565b600061277482612757565b9050919050565b61278481612769565b82525050565b600060608201905061279f600083018661277b565b6127ac602083018561258a565b6127b9604083018461258a565b949350505050565b6127ca816125b9565b82525050565b60006020820190506127e560008301846127c1565b92915050565b6000602082019050612800600083018461277b565b92915050565b61280f8161263e565b82525050565b600060208201905061282a6000830184612806565b92915050565b60008151905061283f816126d2565b92915050565b60006020828403121561285b5761285a6125b4565b5b600061286984828501612830565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006128ac82612580565b91506128b783612580565b9250828210156128ca576128c9612872565b5b828203905092915050565b600082825260208201905092915050565b7f6e6f7420656e6f75676820746f6b656e7320746f2074616b65206f7574000000600082015250565b600061291c601d836128d5565b9150612927826128e6565b602082019050919050565b6000602082019050818103600083015261294b8161290f565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612988601f836128d5565b915061299382612952565b602082019050919050565b600060208201905081810360008301526129b78161297b565b9050919050565b7f4d6179206e6f7420646f206e6f726d616c207769746864726177206561726c79600082015250565b60006129f46020836128d5565b91506129ff826129be565b602082019050919050565b60006020820190508181036000830152612a23816129e7565b9050919050565b7f43616e6e6f74207769746864726177206f746865722070656f706c652773207360008201527f74616b656420746f6b656e732e2020436f6e7461637420616e2061646d696e2e602082015250565b6000612a866040836128d5565b9150612a9182612a2a565b604082019050919050565b60006020820190508181036000830152612ab581612a79565b9050919050565b6000612ac782612580565b9150612ad283612580565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612b0757612b06612872565b5b828201905092915050565b7f43616e206f6e6c792073746172742072657761726473206f6e63650000000000600082015250565b6000612b48601b836128d5565b9150612b5382612b12565b602082019050919050565b60006020820190508181036000830152612b7781612b3b565b9050919050565b7f415052206d7573742062652062656c6f77203130303030250000000000000000600082015250565b6000612bb46018836128d5565b9150612bbf82612b7e565b602082019050919050565b60006020820190508181036000830152612be381612ba7565b9050919050565b7f4d6179206e6f742073657420686967686572207468616e203230250000000000600082015250565b6000612c20601b836128d5565b9150612c2b82612bea565b602082019050919050565b60006020820190508181036000830152612c4f81612c13565b9050919050565b6000612c6182612580565b9150612c6c83612580565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612ca557612ca4612872565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612cea82612580565b9150612cf583612580565b925082612d0557612d04612cb0565b5b828204905092915050565b7f43616e6e6f74207374616b65206d6f7265000000000000000000000000000000600082015250565b6000612d466011836128d5565b9150612d5182612d10565b602082019050919050565b60006020820190508181036000830152612d7581612d39565b9050919050565b7f4c6f636b206d7573742062652033302064617973206f72206c6573732e000000600082015250565b6000612db2601d836128d5565b9150612dbd82612d7c565b602082019050919050565b60006020820190508181036000830152612de181612da5565b9050919050565b7f43616e6e6f7420636f6d706f756e640000000000000000000000000000000000600082015250565b6000612e1e600f836128d5565b9150612e2982612de8565b602082019050919050565b60006020820190508181036000830152612e4d81612e11565b9050919050565b6000604082019050612e696000830185612806565b612e76602083018461258a565b9392505050565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008201527f7700000000000000000000000000000000000000000000000000000000000000602082015250565b6000612ed96021836128d5565b9150612ee482612e7d565b604082019050919050565b60006020820190508181036000830152612f0881612ecc565b9050919050565b6000606082019050612f246000830186612806565b612f316020830185612806565b612f3e604083018461258a565b949350505050565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b6000612f7c601b836128d5565b9150612f8782612f46565b602082019050919050565b60006020820190508181036000830152612fab81612f6f565b9050919050565b600081519050612fc1816125c5565b92915050565b600060208284031215612fdd57612fdc6125b4565b5b6000612feb84828501612fb2565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000613050602a836128d5565b915061305b82612ff4565b604082019050919050565b6000602082019050818103600083015261307f81613043565b9050919050565b600081519050919050565b60005b838110156130af578082015181840152602081019050613094565b838111156130be576000848401525b50505050565b6000601f19601f8301169050919050565b60006130e082613086565b6130ea81856128d5565b93506130fa818560208601613091565b613103816130c4565b840191505092915050565b6000602082019050818103600083015261312881846130d5565b905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000613166601d836128d5565b915061317182613130565b602082019050919050565b6000602082019050818103600083015261319581613159565b9050919050565b600081519050919050565b600081905092915050565b60006131bd8261319c565b6131c781856131a7565b93506131d7818560208601613091565b80840191505092915050565b60006131ef82846131b2565b91508190509291505056fea2646970667358221220078aea9a68930801b6356094dda7b694bb34594afc157cb4cc981b3b4654049d64736f6c634300080e00330000000000000000000000009637829c0c784dc876fdb49f6b47ca544ae38a6200000000000000000000000000000000000000000000000000000000000005dc

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80636352211e11610104578063b88d4fde116100a2578063dd62ed3e11610071578063dd62ed3e14610534578063e0df5b6f14610564578063e985e9c514610580578063f2fde38b146105b0576101cf565b8063b88d4fde146104ac578063c87b56dd146104c8578063d547cfb7146104f8578063d7c64e7f14610516576101cf565b806395d89b41116100de57806395d89b41146104125780639b19251a14610430578063a22cb46514610460578063a9059cbb1461047c576101cf565b80636352211e1461039457806370a08231146103c45780638da5cb5b146103f4576101cf565b80632b9689581161017157806342842e0e1161014b57806342842e0e1461030e5780634f02c4201461032a57806353d6fd591461034857806356bb8cb614610364576101cf565b80632b968958146102c8578063313ce567146102d25780633cd60e06146102f0576101cf565b80630dc91306116101ad5780630dc913061461025257806316f0115b1461027057806318160ddd1461028e57806323b872dd146102ac576101cf565b806306fdde03146101d4578063081812fc146101f2578063095ea7b314610222575b600080fd5b6101dc6105cc565b6040516101e99190612985565b60405180910390f35b61020c600480360381019061020791906129f1565b61065a565b6040516102199190612a5f565b60405180910390f35b61023c60048036038101906102379190612aa6565b61068d565b6040516102499190612b01565b60405180910390f35b61025a610986565b6040516102679190612b7b565b60405180910390f35b6102786109aa565b6040516102859190612a5f565b60405180910390f35b6102966109d0565b6040516102a39190612ba5565b60405180910390f35b6102c660048036038101906102c19190612bc0565b6109f4565b005b6102d061122b565b005b6102da61134e565b6040516102e79190612c2f565b60405180910390f35b6102f8611372565b6040516103059190612c6b565b60405180910390f35b61032860048036038101906103239190612bc0565b611398565b005b6103326114cb565b60405161033f9190612ba5565b60405180910390f35b610362600480360381019061035d9190612cb2565b6114d1565b005b61037e600480360381019061037991906129f1565b6115b1565b60405161038b9190612ba5565b60405180910390f35b6103ae60048036038101906103a991906129f1565b6115d5565b6040516103bb9190612a5f565b60405180910390f35b6103de60048036038101906103d99190612cf2565b611678565b6040516103eb9190612ba5565b60405180910390f35b6103fc611690565b6040516104099190612a5f565b60405180910390f35b61041a6116b4565b6040516104279190612985565b60405180910390f35b61044a60048036038101906104459190612cf2565b611742565b6040516104579190612b01565b60405180910390f35b61047a60048036038101906104759190612cb2565b611762565b005b61049660048036038101906104919190612aa6565b61185f565b6040516104a39190612b01565b60405180910390f35b6104c660048036038101906104c19190612d84565b611874565b005b6104e260048036038101906104dd91906129f1565b6119ad565b6040516104ef9190612985565b60405180910390f35b6105006119e1565b60405161050d9190612985565b60405180910390f35b61051e611a6f565b60405161052b9190612ba5565b60405180910390f35b61054e60048036038101906105499190612e0c565b611a75565b60405161055b9190612ba5565b60405180910390f35b61057e60048036038101906105799190612f7c565b611a9a565b005b61059a60048036038101906105959190612e0c565b611b39565b6040516105a79190612b01565b60405180910390f35b6105ca60048036038101906105c59190612cf2565b611b68565b005b600180546105d990612ff4565b80601f016020809104026020016040519081016040528092919081815260200182805461060590612ff4565b80156106525780601f1061062757610100808354040283529160200191610652565b820191906000526020600020905b81548152906001019060200180831161063557829003601f168201915b505050505081565b60086020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060045482111580156106a15750600082115b15610895576000600a600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156107a15750600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b156107d8576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836008600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516108879190612ba5565b60405180910390a35061097c565b81600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109739190612ba5565b60405180910390a35b6001905092915050565b7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000005150ae84a8cdf0000081565b60045481116110e357600a600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610a95576040517fddb5de5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610afb576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610bbe5750600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b8015610c2957506008600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610c60576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c68611cf0565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610cb69190613054565b92505081905550610cc5611cf0565b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600a600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506008600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050610e299190613054565b81548110610e3a57610e39613088565b5b9060005260206000200154905080600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600c60008581526020019081526020016000205481548110610eac57610eab613088565b5b9060005260206000200181905550600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480610f0957610f086130b7565b5b60019003818190600052602060002001600090559055600c600083815260200190815260200160002054600c600083815260200190815260200160002081905550600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208290806001815401808255809150506001900390600052602060002001600090919091909150556001600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050610fff9190613054565b600c600084815260200190815260200160002081905550818373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fe59fdd36d0d223c0c7d996db7ad796880f45e1936cb0bb7ac102e7082e0314876110c8611cf0565b6040516110d59190612ba5565b60405180910390a350611226565b6000600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146112185781816111979190613054565b600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b611223848484611d24565b50505b505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112b0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3565b7f000000000000000000000000000000000000000000000000000000000000001281565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6113a38383836109f4565b60008273ffffffffffffffffffffffffffffffffffffffff163b1415801561148f575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168273ffffffffffffffffffffffffffffffffffffffff1663150b7a023386856040518463ffffffff1660e01b815260040161142a9392919061311d565b6020604051808303816000875af1158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d91906131bf565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614155b156114c6576040517f3da6393100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60045481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611556576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600381815481106115c157600080fd5b906000526020600020016000915090505481565b6000600a600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611673576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60066020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600280546116c190612ff4565b80601f01602080910402602001604051908101604052809291908181526020018280546116ed90612ff4565b801561173a5780601f1061170f5761010080835404028352916020019161173a565b820191906000526020600020905b81548152906001019060200180831161171d57829003601f168201915b505050505081565b600d6020528060005260406000206000915054906101000a900460ff1681565b80600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516118539190612b01565b60405180910390a35050565b600061186c338484611d24565b905092915050565b61187f8585856109f4565b60008473ffffffffffffffffffffffffffffffffffffffff163b1415801561196f575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff1663150b7a0233888787876040518663ffffffff1660e01b815260040161190a959493929190613219565b6020604051808303816000875af1158015611929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194d91906131bf565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614155b156119a6576040517f3da6393100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6060600f6119ba8361208f565b6040516020016119cb929190613337565b6040516020818303038152906040529050919050565b600f80546119ee90612ff4565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1a90612ff4565b8015611a675780601f10611a3c57610100808354040283529160200191611a67565b820191906000526020600020905b815481529060010190602001808311611a4a57829003601f168201915b505050505081565b60055481565b6007602052816000526040600020602052806000526040600020600091509150505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b1f576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600f9080519060200190611b35929190612849565b5050565b60096020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bed576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611c53576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b60007f0000000000000000000000000000000000000000000000000000000000000012600a611d1f919061348e565b905090565b600080611d2f611cf0565b90506000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905084600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611e089190613054565b9250508190555084600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611f3c57600083600660008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611efa9190613508565b8484611f069190613508565b611f109190613054565b905060005b81811015611f3957611f268961215d565b8080611f3190613539565b915050611f15565b50505b600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661201c5760008382611f9b9190613508565b84600660008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611fe69190613508565b611ff09190613054565b905060005b8181101561201957612006886123e2565b808061201190613539565b915050611ff5565b50505b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fe59fdd36d0d223c0c7d996db7ad796880f45e1936cb0bb7ac102e7082e031487876040516120799190612ba5565b60405180910390a3600193505050509392505050565b60606000600161209e846126f6565b01905060008167ffffffffffffffff8111156120bd576120bc612e51565b5b6040519080825280601f01601f1916602001820160405280156120ef5781602001600182028036833780820191505090505b509050600082602001820190505b600115612152578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612146576121456134d9565b5b049450600085036120fd575b819350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121c3576040517fddb5de5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506122539190613054565b8154811061226457612263613088565b5b90600052602060002001549050600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806122c0576122bf6130b7565b5b60019003818190600052602060002001600090559055600c600082815260200190815260200160002060009055600a600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600381908060018154018082558091505060019003906000526020600020016000909190919091505580600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612448576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004600081548092919060010191905055506000600454905060055460045411801561247957506000600380549050115b156124df57600060016003805490506124929190613054565b9050600381815481106124a8576124a7613088565b5b9060005260206000200154915060038054806124c7576124c66130b7565b5b60019003818190600052602060002001600090559055505b600073ffffffffffffffffffffffffffffffffffffffff16600a600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612578576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600a600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150556001600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061267f9190613054565b600c600083815260200190815260200160002081905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612754577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161274a576127496134d9565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612791576d04ee2d6d415b85acef81000000008381612787576127866134d9565b5b0492506020810190505b662386f26fc1000083106127c057662386f26fc1000083816127b6576127b56134d9565b5b0492506010810190505b6305f5e10083106127e9576305f5e10083816127df576127de6134d9565b5b0492506008810190505b612710831061280e576127108381612804576128036134d9565b5b0492506004810190505b606483106128315760648381612827576128266134d9565b5b0492506002810190505b600a8310612840576001810190505b80915050919050565b82805461285590612ff4565b90600052602060002090601f01602090048101928261287757600085556128be565b82601f1061289057805160ff19168380011785556128be565b828001600101855582156128be579182015b828111156128bd5782518255916020019190600101906128a2565b5b5090506128cb91906128cf565b5090565b5b808211156128e85760008160009055506001016128d0565b5090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561292657808201518184015260208101905061290b565b83811115612935576000848401525b50505050565b6000601f19601f8301169050919050565b6000612957826128ec565b61296181856128f7565b9350612971818560208601612908565b61297a8161293b565b840191505092915050565b6000602082019050818103600083015261299f818461294c565b905092915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6129ce816129bb565b81146129d957600080fd5b50565b6000813590506129eb816129c5565b92915050565b600060208284031215612a0757612a066129b1565b5b6000612a15848285016129dc565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612a4982612a1e565b9050919050565b612a5981612a3e565b82525050565b6000602082019050612a746000830184612a50565b92915050565b612a8381612a3e565b8114612a8e57600080fd5b50565b600081359050612aa081612a7a565b92915050565b60008060408385031215612abd57612abc6129b1565b5b6000612acb85828601612a91565b9250506020612adc858286016129dc565b9150509250929050565b60008115159050919050565b612afb81612ae6565b82525050565b6000602082019050612b166000830184612af2565b92915050565b6000819050919050565b6000612b41612b3c612b3784612a1e565b612b1c565b612a1e565b9050919050565b6000612b5382612b26565b9050919050565b6000612b6582612b48565b9050919050565b612b7581612b5a565b82525050565b6000602082019050612b906000830184612b6c565b92915050565b612b9f816129bb565b82525050565b6000602082019050612bba6000830184612b96565b92915050565b600080600060608486031215612bd957612bd86129b1565b5b6000612be786828701612a91565b9350506020612bf886828701612a91565b9250506040612c09868287016129dc565b9150509250925092565b600060ff82169050919050565b612c2981612c13565b82525050565b6000602082019050612c446000830184612c20565b92915050565b6000612c5582612b48565b9050919050565b612c6581612c4a565b82525050565b6000602082019050612c806000830184612c5c565b92915050565b612c8f81612ae6565b8114612c9a57600080fd5b50565b600081359050612cac81612c86565b92915050565b60008060408385031215612cc957612cc86129b1565b5b6000612cd785828601612a91565b9250506020612ce885828601612c9d565b9150509250929050565b600060208284031215612d0857612d076129b1565b5b6000612d1684828501612a91565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612d4457612d43612d1f565b5b8235905067ffffffffffffffff811115612d6157612d60612d24565b5b602083019150836001820283011115612d7d57612d7c612d29565b5b9250929050565b600080600080600060808688031215612da057612d9f6129b1565b5b6000612dae88828901612a91565b9550506020612dbf88828901612a91565b9450506040612dd0888289016129dc565b935050606086013567ffffffffffffffff811115612df157612df06129b6565b5b612dfd88828901612d2e565b92509250509295509295909350565b60008060408385031215612e2357612e226129b1565b5b6000612e3185828601612a91565b9250506020612e4285828601612a91565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612e898261293b565b810181811067ffffffffffffffff82111715612ea857612ea7612e51565b5b80604052505050565b6000612ebb6129a7565b9050612ec78282612e80565b919050565b600067ffffffffffffffff821115612ee757612ee6612e51565b5b612ef08261293b565b9050602081019050919050565b82818337600083830152505050565b6000612f1f612f1a84612ecc565b612eb1565b905082815260208101848484011115612f3b57612f3a612e4c565b5b612f46848285612efd565b509392505050565b600082601f830112612f6357612f62612d1f565b5b8135612f73848260208601612f0c565b91505092915050565b600060208284031215612f9257612f916129b1565b5b600082013567ffffffffffffffff811115612fb057612faf6129b6565b5b612fbc84828501612f4e565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061300c57607f821691505b60208210810361301f5761301e612fc5565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061305f826129bb565b915061306a836129bb565b92508282101561307d5761307c613025565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082825260208201905092915050565b50565b60006131076000836130e6565b9150613112826130f7565b600082019050919050565b60006080820190506131326000830186612a50565b61313f6020830185612a50565b61314c6040830184612b96565b818103606083015261315d816130fa565b9050949350505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61319c81613167565b81146131a757600080fd5b50565b6000815190506131b981613193565b92915050565b6000602082840312156131d5576131d46129b1565b5b60006131e3848285016131aa565b91505092915050565b60006131f883856130e6565b9350613205838584612efd565b61320e8361293b565b840190509392505050565b600060808201905061322e6000830188612a50565b61323b6020830187612a50565b6132486040830186612b96565b818103606083015261325b8184866131ec565b90509695505050505050565b600081905092915050565b60008190508160005260206000209050919050565b6000815461329481612ff4565b61329e8186613267565b945060018216600081146132b957600181146132ca576132fd565b60ff198316865281860193506132fd565b6132d385613272565b60005b838110156132f5578154818901526001820191506020810190506132d6565b838801955050505b50505092915050565b6000613311826128ec565b61331b8185613267565b935061332b818560208601612908565b80840191505092915050565b60006133438285613287565b915061334f8284613306565b91508190509392505050565b60008160011c9050919050565b6000808291508390505b60018511156133b25780860481111561338e5761338d613025565b5b600185161561339d5780820291505b80810290506133ab8561335b565b9450613372565b94509492505050565b6000826133cb5760019050613487565b816133d95760009050613487565b81600181146133ef57600281146133f957613428565b6001915050613487565b60ff84111561340b5761340a613025565b5b8360020a91508482111561342257613421613025565b5b50613487565b5060208310610133831016604e8410600b841016171561345d5782820a90508381111561345857613457613025565b5b613487565b61346a8484846001613368565b9250905081840481111561348157613480613025565b5b81810290505b9392505050565b6000613499826129bb565b91506134a483612c13565b92506134d17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846133bb565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613513826129bb565b915061351e836129bb565b92508261352e5761352d6134d9565b5b828204905092915050565b6000613544826129bb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361357657613575613025565b5b60018201905091905056fea26469706673582212201180cd6399806b592955f99517cb4c5263046852e76d3b757a019ad7e18f358364736f6c634300080e0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000009637829c0c784dc876fdb49f6b47ca544ae38a6200000000000000000000000000000000000000000000000000000000000005dc

-----Decoded View---------------
Arg [0] : _owner (address): 0x9637829C0C784DC876fdb49F6b47cA544ae38A62
Arg [1] : _supply (uint256): 1500

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009637829c0c784dc876fdb49f6b47ca544ae38a62
Arg [1] : 00000000000000000000000000000000000000000000000000000000000005dc


Deployed Bytecode Sourcemap

60968:1624:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2156:18;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3066:46;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4978:642;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61009:42;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61058:19;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2392:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6027:1716;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;872:151;;;:::i;:::-;;2292:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61117:46;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8039:405;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2604:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4307:111;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2473:32;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4490:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2832:44;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;313:20;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2210;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3677:41;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5671:207;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7802:160;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8539:437;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62439:150;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61084:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2724:23;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2946:64;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62325:106;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3177:68;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;645:219;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2156:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3066:46::-;;;;;;;;;;;;;;;;;;;;;;:::o;4978:642::-;5081:4;5116:6;;5102:10;:20;;:38;;;;;5139:1;5126:10;:14;5102:38;5098:491;;;5157:13;5173:8;:20;5182:10;5173:20;;;;;;;;;;;;;;;;;;;;;5157:36;;5228:5;5214:19;;:10;:19;;;;:59;;;;;5238:16;:23;5255:5;5238:23;;;;;;;;;;;;;;;:35;5262:10;5238:35;;;;;;;;;;;;;;;;;;;;;;;;;5237:36;5214:59;5210:121;;;5301:14;;;;;;;;;;;;;;5210:121;5373:7;5347:11;:23;5359:10;5347:23;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;5418:7;5402:36;;5411:5;5402:36;;;5427:10;5402:36;;;;;;:::i;:::-;;;;;;;;5142:308;5098:491;;;5504:10;5471:9;:21;5481:10;5471:21;;;;;;;;;;;;;;;:30;5493:7;5471:30;;;;;;;;;;;;;;;:43;;;;5557:7;5536:41;;5545:10;5536:41;;;5566:10;5536:41;;;;;;:::i;:::-;;;;;;;;5098:491;5608:4;5601:11;;4978:642;;;;:::o;61009:42::-;;;:::o;61058:19::-;;;;;;;;;;;;;:::o;2392:36::-;;;:::o;6027:1716::-;6173:6;;6159:10;:20;6155:1581;;6208:8;:20;6217:10;6208:20;;;;;;;;;;;;;;;;;;;;;6200:28;;:4;:28;;;6196:91;;6256:15;;;;;;;;;;;;;;6196:91;6321:1;6307:16;;:2;:16;;;6303:82;;6351:18;;;;;;;;;;;;;;6303:82;6437:4;6423:18;;:10;:18;;;;:74;;;;;6463:16;:22;6480:4;6463:22;;;;;;;;;;;;;;;:34;6486:10;6463:34;;;;;;;;;;;;;;;;;;;;;;;;;6462:35;6423:74;:132;;;;;6532:11;:23;6544:10;6532:23;;;;;;;;;;;;;;;;;;;;;6518:37;;:10;:37;;;;6423:132;6401:226;;;6597:14;;;;;;;;;;;;;;6401:226;6662:10;:8;:10::i;:::-;6643:9;:15;6653:4;6643:15;;;;;;;;;;;;;;;;:29;;;;;;;:::i;:::-;;;;;;;;6735:10;:8;:10::i;:::-;6718:9;:13;6728:2;6718:13;;;;;;;;;;;;;;;;:27;;;;;;;;;;;6800:2;6777:8;:20;6786:10;6777:20;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;6824:11;:23;6836:10;6824:23;;;;;;;;;;;;6817:30;;;;;;;;;;;6905:17;6925:6;:12;6932:4;6925:12;;;;;;;;;;;;;;;6960:1;6938:6;:12;6945:4;6938:12;;;;;;;;;;;;;;;:19;;;;:23;;;;:::i;:::-;6925:37;;;;;;;;:::i;:::-;;;;;;;;;;6905:57;;7017:9;6977:6;:12;6984:4;6977:12;;;;;;;;;;;;;;;6990:11;:23;7002:10;6990:23;;;;;;;;;;;;6977:37;;;;;;;;:::i;:::-;;;;;;;;;:49;;;;7061:6;:12;7068:4;7061:12;;;;;;;;;;;;;;;:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;7165:11;:23;7177:10;7165:23;;;;;;;;;;;;7140:11;:22;7152:9;7140:22;;;;;;;;;;;:48;;;;7242:6;:10;7249:2;7242:10;;;;;;;;;;;;;;;7258;7242:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7372:1;7352:6;:10;7359:2;7352:10;;;;;;;;;;;;;;;:17;;;;:21;;;;:::i;:::-;7326:11;:23;7338:10;7326:23;;;;;;;;;;;:47;;;;7414:10;7410:2;7395:30;;7404:4;7395:30;;;;;;;;;;;;7465:2;7445:35;;7459:4;7445:35;;;7469:10;:8;:10::i;:::-;7445:35;;;;;;:::i;:::-;;;;;;;;6181:1311;6155:1581;;;7513:15;7531:9;:15;7541:4;7531:15;;;;;;;;;;;;;;;:27;7547:10;7531:27;;;;;;;;;;;;;;;;7513:45;;7590:17;7579:7;:28;7575:101;;7666:10;7656:7;:20;;;;:::i;:::-;7626:9;:15;7636:4;7626:15;;;;;;;;;;;;;;;:27;7642:10;7626:27;;;;;;;;;;;;;;;:50;;;;7575:101;7693:31;7703:4;7709:2;7713:10;7693:9;:31::i;:::-;;7498:238;6155:1581;6027:1716;;;:::o;872:151::-;400:5;;;;;;;;;;386:19;;:10;:19;;;382:46;;414:14;;;;;;;;;;;;;;382:46;951:1:::1;935:5:::0;::::1;:18;;;;;;;;;;;;;;;;;;1012:1;971:44;;992:10;971:44;;;;;;;;;;;;872:151::o:0;2292:31::-;;;:::o;61117:46::-;;;;;;;;;;;;;:::o;8039:405::-;8163:26;8176:4;8182:2;8186;8163:12;:26::i;:::-;8238:1;8220:2;:14;;;:19;;:154;;;;;8334:40;;;8256:118;;;8271:2;8256:35;;;8292:10;8304:4;8310:2;8256:61;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:118;;;;;8220:154;8202:235;;;8408:17;;;;;;;;;;;;;;8202:235;8039:405;;;:::o;2604:21::-;;;;:::o;4307:111::-;400:5;;;;;;;;;;386:19;;:10;:19;;;382:46;;414:14;;;;;;;;;;;;;;382:46;4405:5:::1;4385:9;:17;4395:6;4385:17;;;;;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;4307:111:::0;;:::o;2473:32::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;4490:193::-;4548:13;4582:8;:12;4591:2;4582:12;;;;;;;;;;;;;;;;;;;;;4574:20;;4628:1;4611:19;;:5;:19;;;4607:69;;4654:10;;;;;;;;;;;;;;4607:69;4490:193;;;:::o;2832:44::-;;;;;;;;;;;;;;;;;:::o;313:20::-;;;;;;;;;;;;:::o;2210:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3677:41::-;;;;;;;;;;;;;;;;;;;;;;:::o;5671:207::-;5798:8;5757:16;:28;5774:10;5757:28;;;;;;;;;;;;;;;:38;5786:8;5757:38;;;;;;;;;;;;;;;;:49;;;;;;;;;;;;;;;;;;5851:8;5824:46;;5839:10;5824:46;;;5861:8;5824:46;;;;;;:::i;:::-;;;;;;;;5671:207;;:::o;7802:160::-;7897:4;7921:33;7931:10;7943:2;7947:6;7921:9;:33::i;:::-;7914:40;;7802:160;;;;:::o;8539:437::-;8693:26;8706:4;8712:2;8716;8693:12;:26::i;:::-;8768:1;8750:2;:14;;;:19;;:156;;;;;8866:40;;;8786:120;;;8801:2;8786:35;;;8822:10;8834:4;8840:2;8844:4;;8786:63;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:120;;;;;8750:156;8732:237;;;8940:17;;;;;;;;;;;;;;8732:237;8539:437;;;;;:::o;62439:150::-;62499:13;62546:12;62560:20;62577:2;62560:16;:20::i;:::-;62532:49;;;;;;;;;:::i;:::-;;;;;;;;;;;;;62525:56;;62439:150;;;:::o;61084:26::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2724:23::-;;;;:::o;2946:64::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;62325:106::-;400:5;;;;;;;;;;386:19;;:10;:19;;;382:46;;414:14;;;;;;;;;;;;;;382:46;62414:9:::1;62399:12;:24;;;;;;;;;;;;:::i;:::-;;62325:106:::0;:::o;3177:68::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;645:219::-;400:5;;;;;;;;;;386:19;;:10;:19;;;382:46;;414:14;;;;;;;;;;;;;;382:46;746:1:::1;728:20;;:6;:20;;::::0;724:47:::1;;757:14;;;;;;;;;;;;;;724:47;792:6;784:5;::::0;:14:::1;;;;;;;;;;;;;;;;;;849:6;816:40;;837:10;816:40;;;;;;;;;;;;645:219:::0;:::o;10176:92::-;10219:7;10252:8;10246:2;:14;;;;:::i;:::-;10239:21;;10176:92;:::o;9044:1093::-;9157:4;9174:12;9189:10;:8;:10::i;:::-;9174:25;;9210:27;9240:9;:15;9250:4;9240:15;;;;;;;;;;;;;;;;9210:45;;9266:29;9298:9;:13;9308:2;9298:13;;;;;;;;;;;;;;;;9266:45;;9343:6;9324:9;:15;9334:4;9324:15;;;;;;;;;;;;;;;;:25;;;;;;;:::i;:::-;;;;;;;;9404:6;9387:9;:13;9397:2;9387:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;9495:9;:15;9505:4;9495:15;;;;;;;;;;;;;;;;;;;;;;;;;9490:251;;9527:22;9619:4;9601:9;:15;9611:4;9601:15;;;;;;;;;;;;;;;;:22;;;;:::i;:::-;9575:4;9553:19;:26;;;;:::i;:::-;9552:72;;;;:::i;:::-;9527:97;;9644:9;9639:91;9663:14;9659:1;:18;9639:91;;;9703:11;9709:4;9703:5;:11::i;:::-;9679:3;;;;;:::i;:::-;;;;9639:91;;;;9512:229;9490:251;9817:9;:13;9827:2;9817:13;;;;;;;;;;;;;;;;;;;;;;;;;9812:247;;9847:22;9939:4;9915:21;:28;;;;:::i;:::-;9889:4;9873:9;:13;9883:2;9873:13;;;;;;;;;;;;;;;;:20;;;;:::i;:::-;9872:72;;;;:::i;:::-;9847:97;;9964:9;9959:89;9983:14;9979:1;:18;9959:89;;;10023:9;10029:2;10023:5;:9::i;:::-;9999:3;;;;;:::i;:::-;;;;9959:89;;;;9832:227;9812:247;10096:2;10076:31;;10090:4;10076:31;;;10100:6;10076:31;;;;;;:::i;:::-;;;;;;;;10125:4;10118:11;;;;;9044:1093;;;;;:::o;28530:718::-;28586:13;28637:14;28674:1;28654:17;28665:5;28654:10;:17::i;:::-;:21;28637:38;;28690:20;28724:6;28713:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28690:41;;28746:11;28875:6;28871:2;28867:15;28859:6;28855:28;28848:35;;28912:290;28919:4;28912:290;;;28944:5;;;;;;;;29086:10;29081:2;29074:5;29070:14;29065:32;29060:3;29052:46;29144:2;29135:11;;;;;;:::i;:::-;;;;;29178:1;29169:5;:10;28912:290;29165:21;28912:290;29223:6;29216:13;;;;;28530:718;;;:::o;10976:452::-;11053:1;11037:18;;:4;:18;;;11033:73;;11079:15;;;;;;;;;;;;;;11033:73;11118:10;11131:6;:12;11138:4;11131:12;;;;;;;;;;;;;;;11166:1;11144:6;:12;11151:4;11144:12;;;;;;;;;;;;;;;:19;;;;:23;;;;:::i;:::-;11131:37;;;;;;;;:::i;:::-;;;;;;;;;;11118:50;;11179:6;:12;11186:4;11179:12;;;;;;;;;;;;;;;:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;11215:11;:15;11227:2;11215:15;;;;;;;;;;;11208:22;;;11248:8;:12;11257:2;11248:12;;;;;;;;;;;;11241:19;;;;;;;;;;;11278:11;:15;11290:2;11278:15;;;;;;;;;;;;11271:22;;;;;;;;;;;11348:15;11369:2;11348:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11417:2;11413:1;11390:30;;11399:4;11390:30;;;;;;;;;;;;11022:406;10976:452;:::o;10276:692::-;10349:1;10335:16;;:2;:16;;;10331:74;;10375:18;;;;;;;;;;;;;;10331:74;10442:6;;:8;;;;;;;;;;;;;10474:10;10487:6;;10474:19;;10518:8;;10509:6;;:17;:47;;;;;10555:1;10530:15;:22;;;;:26;10509:47;10506:206;;;10572:17;10617:1;10592:15;:22;;;;:26;;;;:::i;:::-;10572:46;;10638:15;10654:9;10638:26;;;;;;;;:::i;:::-;;;;;;;;;;10633:31;;10679:15;:21;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;10557:155;10506:206;10752:1;10728:26;;:8;:12;10737:2;10728:12;;;;;;;;;;;;;;;;;;;;;:26;;;10724:81;;10778:15;;;;;;;;;;;;;;10724:81;10832:2;10817:8;:12;10826:2;10817:12;;;;;;;;;;;;:17;;;;;;;;;;;;;;;;;;10845:6;:10;10852:2;10845:10;;;;;;;;;;;;;;;10861:2;10845:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10913:1;10893:6;:10;10900:2;10893:10;;;;;;;;;;;;;;;:17;;;;:21;;;;:::i;:::-;10875:11;:15;10887:2;10875:15;;;;;;;;;;;:39;;;;10957:2;10953;10932:28;;10949:1;10932:28;;;;;;;;;;;;10320:648;10276:692;:::o;23926:948::-;23979:7;23999:14;24016:1;23999:18;;24066:8;24057:5;:17;24053:106;;24104:8;24095:17;;;;;;:::i;:::-;;;;;24141:2;24131:12;;;;24053:106;24186:8;24177:5;:17;24173:106;;24224:8;24215:17;;;;;;:::i;:::-;;;;;24261:2;24251:12;;;;24173:106;24306:8;24297:5;:17;24293:106;;24344:8;24335:17;;;;;;:::i;:::-;;;;;24381:2;24371:12;;;;24293:106;24426:7;24417:5;:16;24413:103;;24463:7;24454:16;;;;;;:::i;:::-;;;;;24499:1;24489:11;;;;24413:103;24543:7;24534:5;:16;24530:103;;24580:7;24571:16;;;;;;:::i;:::-;;;;;24616:1;24606:11;;;;24530:103;24660:7;24651:5;:16;24647:103;;24697:7;24688:16;;;;;;:::i;:::-;;;;;24733:1;24723:11;;;;24647:103;24777:7;24768:5;:16;24764:68;;24815:1;24805:11;;;;24764:68;24860:6;24853:13;;;23926:948;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::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:307::-;355:1;365:113;379:6;376:1;373:13;365:113;;;464:1;459:3;455:11;449:18;445:1;440:3;436:11;429:39;401:2;398:1;394:10;389:15;;365:113;;;496:6;493:1;490:13;487:101;;;576:1;567:6;562:3;558:16;551:27;487:101;336:258;287:307;;;:::o;600:102::-;641:6;692:2;688:7;683:2;676:5;672:14;668:28;658:38;;600:102;;;:::o;708:364::-;796:3;824:39;857:5;824:39;:::i;:::-;879:71;943:6;938:3;879:71;:::i;:::-;872:78;;959:52;1004:6;999:3;992:4;985:5;981:16;959:52;:::i;:::-;1036:29;1058:6;1036:29;:::i;:::-;1031:3;1027:39;1020:46;;800:272;708:364;;;;:::o;1078:313::-;1191:4;1229:2;1218:9;1214:18;1206:26;;1278:9;1272:4;1268:20;1264:1;1253:9;1249:17;1242:47;1306:78;1379:4;1370:6;1306:78;:::i;:::-;1298:86;;1078:313;;;;:::o;1397:75::-;1430:6;1463:2;1457:9;1447:19;;1397:75;:::o;1478:117::-;1587:1;1584;1577:12;1601:117;1710:1;1707;1700:12;1724:77;1761:7;1790:5;1779:16;;1724:77;;;:::o;1807:122::-;1880:24;1898:5;1880:24;:::i;:::-;1873:5;1870:35;1860:63;;1919:1;1916;1909:12;1860:63;1807:122;:::o;1935:139::-;1981:5;2019:6;2006:20;1997:29;;2035:33;2062:5;2035:33;:::i;:::-;1935:139;;;;:::o;2080:329::-;2139:6;2188:2;2176:9;2167:7;2163:23;2159:32;2156:119;;;2194:79;;:::i;:::-;2156:119;2314:1;2339:53;2384:7;2375:6;2364:9;2360:22;2339:53;:::i;:::-;2329:63;;2285:117;2080:329;;;;:::o;2415:126::-;2452:7;2492:42;2485:5;2481:54;2470:65;;2415:126;;;:::o;2547:96::-;2584:7;2613:24;2631:5;2613:24;:::i;:::-;2602:35;;2547:96;;;:::o;2649:118::-;2736:24;2754:5;2736:24;:::i;:::-;2731:3;2724:37;2649:118;;:::o;2773:222::-;2866:4;2904:2;2893:9;2889:18;2881:26;;2917:71;2985:1;2974:9;2970:17;2961:6;2917:71;:::i;:::-;2773:222;;;;:::o;3001:122::-;3074:24;3092:5;3074:24;:::i;:::-;3067:5;3064:35;3054:63;;3113:1;3110;3103:12;3054:63;3001:122;:::o;3129:139::-;3175:5;3213:6;3200:20;3191:29;;3229:33;3256:5;3229:33;:::i;:::-;3129:139;;;;:::o;3274:474::-;3342:6;3350;3399:2;3387:9;3378:7;3374:23;3370:32;3367:119;;;3405:79;;:::i;:::-;3367:119;3525:1;3550:53;3595:7;3586:6;3575:9;3571:22;3550:53;:::i;:::-;3540:63;;3496:117;3652:2;3678:53;3723:7;3714:6;3703:9;3699:22;3678:53;:::i;:::-;3668:63;;3623:118;3274:474;;;;;:::o;3754:90::-;3788:7;3831:5;3824:13;3817:21;3806:32;;3754:90;;;:::o;3850:109::-;3931:21;3946:5;3931:21;:::i;:::-;3926:3;3919:34;3850:109;;:::o;3965:210::-;4052:4;4090:2;4079:9;4075:18;4067:26;;4103:65;4165:1;4154:9;4150:17;4141:6;4103:65;:::i;:::-;3965:210;;;;:::o;4181:60::-;4209:3;4230:5;4223:12;;4181:60;;;:::o;4247:142::-;4297:9;4330:53;4348:34;4357:24;4375:5;4357:24;:::i;:::-;4348:34;:::i;:::-;4330:53;:::i;:::-;4317:66;;4247:142;;;:::o;4395:126::-;4445:9;4478:37;4509:5;4478:37;:::i;:::-;4465:50;;4395:126;;;:::o;4527:151::-;4602:9;4635:37;4666:5;4635:37;:::i;:::-;4622:50;;4527:151;;;:::o;4684:181::-;4796:62;4852:5;4796:62;:::i;:::-;4791:3;4784:75;4684:181;;:::o;4871:272::-;4989:4;5027:2;5016:9;5012:18;5004:26;;5040:96;5133:1;5122:9;5118:17;5109:6;5040:96;:::i;:::-;4871:272;;;;:::o;5149:118::-;5236:24;5254:5;5236:24;:::i;:::-;5231:3;5224:37;5149:118;;:::o;5273:222::-;5366:4;5404:2;5393:9;5389:18;5381:26;;5417:71;5485:1;5474:9;5470:17;5461:6;5417:71;:::i;:::-;5273:222;;;;:::o;5501:619::-;5578:6;5586;5594;5643:2;5631:9;5622:7;5618:23;5614:32;5611:119;;;5649:79;;:::i;:::-;5611:119;5769:1;5794:53;5839:7;5830:6;5819:9;5815:22;5794:53;:::i;:::-;5784:63;;5740:117;5896:2;5922:53;5967:7;5958:6;5947:9;5943:22;5922:53;:::i;:::-;5912:63;;5867:118;6024:2;6050:53;6095:7;6086:6;6075:9;6071:22;6050:53;:::i;:::-;6040:63;;5995:118;5501:619;;;;;:::o;6126:86::-;6161:7;6201:4;6194:5;6190:16;6179:27;;6126:86;;;:::o;6218:112::-;6301:22;6317:5;6301:22;:::i;:::-;6296:3;6289:35;6218:112;;:::o;6336:214::-;6425:4;6463:2;6452:9;6448:18;6440:26;;6476:67;6540:1;6529:9;6525:17;6516:6;6476:67;:::i;:::-;6336:214;;;;:::o;6556:150::-;6630:9;6663:37;6694:5;6663:37;:::i;:::-;6650:50;;6556:150;;;:::o;6712:179::-;6823:61;6878:5;6823:61;:::i;:::-;6818:3;6811:74;6712:179;;:::o;6897:270::-;7014:4;7052:2;7041:9;7037:18;7029:26;;7065:95;7157:1;7146:9;7142:17;7133:6;7065:95;:::i;:::-;6897:270;;;;:::o;7173:116::-;7243:21;7258:5;7243:21;:::i;:::-;7236:5;7233:32;7223:60;;7279:1;7276;7269:12;7223:60;7173:116;:::o;7295:133::-;7338:5;7376:6;7363:20;7354:29;;7392:30;7416:5;7392:30;:::i;:::-;7295:133;;;;:::o;7434:468::-;7499:6;7507;7556:2;7544:9;7535:7;7531:23;7527:32;7524:119;;;7562:79;;:::i;:::-;7524:119;7682:1;7707:53;7752:7;7743:6;7732:9;7728:22;7707:53;:::i;:::-;7697:63;;7653:117;7809:2;7835:50;7877:7;7868:6;7857:9;7853:22;7835:50;:::i;:::-;7825:60;;7780:115;7434:468;;;;;:::o;7908:329::-;7967:6;8016:2;8004:9;7995:7;7991:23;7987:32;7984:119;;;8022:79;;:::i;:::-;7984:119;8142:1;8167:53;8212:7;8203:6;8192:9;8188:22;8167:53;:::i;:::-;8157:63;;8113:117;7908:329;;;;:::o;8243:117::-;8352:1;8349;8342:12;8366:117;8475:1;8472;8465:12;8489:117;8598:1;8595;8588:12;8625:552;8682:8;8692:6;8742:3;8735:4;8727:6;8723:17;8719:27;8709:122;;8750:79;;:::i;:::-;8709:122;8863:6;8850:20;8840:30;;8893:18;8885:6;8882:30;8879:117;;;8915:79;;:::i;:::-;8879:117;9029:4;9021:6;9017:17;9005:29;;9083:3;9075:4;9067:6;9063:17;9053:8;9049:32;9046:41;9043:128;;;9090:79;;:::i;:::-;9043:128;8625:552;;;;;:::o;9183:963::-;9280:6;9288;9296;9304;9312;9361:3;9349:9;9340:7;9336:23;9332:33;9329:120;;;9368:79;;:::i;:::-;9329:120;9488:1;9513:53;9558:7;9549:6;9538:9;9534:22;9513:53;:::i;:::-;9503:63;;9459:117;9615:2;9641:53;9686:7;9677:6;9666:9;9662:22;9641:53;:::i;:::-;9631:63;;9586:118;9743:2;9769:53;9814:7;9805:6;9794:9;9790:22;9769:53;:::i;:::-;9759:63;;9714:118;9899:2;9888:9;9884:18;9871:32;9930:18;9922:6;9919:30;9916:117;;;9952:79;;:::i;:::-;9916:117;10065:64;10121:7;10112:6;10101:9;10097:22;10065:64;:::i;:::-;10047:82;;;;9842:297;9183:963;;;;;;;;:::o;10152:474::-;10220:6;10228;10277:2;10265:9;10256:7;10252:23;10248:32;10245:119;;;10283:79;;:::i;:::-;10245:119;10403:1;10428:53;10473:7;10464:6;10453:9;10449:22;10428:53;:::i;:::-;10418:63;;10374:117;10530:2;10556:53;10601:7;10592:6;10581:9;10577:22;10556:53;:::i;:::-;10546:63;;10501:118;10152:474;;;;;:::o;10632:117::-;10741:1;10738;10731:12;10755:180;10803:77;10800:1;10793:88;10900:4;10897:1;10890:15;10924:4;10921:1;10914:15;10941:281;11024:27;11046:4;11024:27;:::i;:::-;11016:6;11012:40;11154:6;11142:10;11139:22;11118:18;11106:10;11103:34;11100:62;11097:88;;;11165:18;;:::i;:::-;11097:88;11205:10;11201:2;11194:22;10984:238;10941:281;;:::o;11228:129::-;11262:6;11289:20;;:::i;:::-;11279:30;;11318:33;11346:4;11338:6;11318:33;:::i;:::-;11228:129;;;:::o;11363:308::-;11425:4;11515:18;11507:6;11504:30;11501:56;;;11537:18;;:::i;:::-;11501:56;11575:29;11597:6;11575:29;:::i;:::-;11567:37;;11659:4;11653;11649:15;11641:23;;11363:308;;;:::o;11677:154::-;11761:6;11756:3;11751;11738:30;11823:1;11814:6;11809:3;11805:16;11798:27;11677:154;;;:::o;11837:412::-;11915:5;11940:66;11956:49;11998:6;11956:49;:::i;:::-;11940:66;:::i;:::-;11931:75;;12029:6;12022:5;12015:21;12067:4;12060:5;12056:16;12105:3;12096:6;12091:3;12087:16;12084:25;12081:112;;;12112:79;;:::i;:::-;12081:112;12202:41;12236:6;12231:3;12226;12202:41;:::i;:::-;11921:328;11837:412;;;;;:::o;12269:340::-;12325:5;12374:3;12367:4;12359:6;12355:17;12351:27;12341:122;;12382:79;;:::i;:::-;12341:122;12499:6;12486:20;12524:79;12599:3;12591:6;12584:4;12576:6;12572:17;12524:79;:::i;:::-;12515:88;;12331:278;12269:340;;;;:::o;12615:509::-;12684:6;12733:2;12721:9;12712:7;12708:23;12704:32;12701:119;;;12739:79;;:::i;:::-;12701:119;12887:1;12876:9;12872:17;12859:31;12917:18;12909:6;12906:30;12903:117;;;12939:79;;:::i;:::-;12903:117;13044:63;13099:7;13090:6;13079:9;13075:22;13044:63;:::i;:::-;13034:73;;12830:287;12615:509;;;;:::o;13130:180::-;13178:77;13175:1;13168:88;13275:4;13272:1;13265:15;13299:4;13296:1;13289:15;13316:320;13360:6;13397:1;13391:4;13387:12;13377:22;;13444:1;13438:4;13434:12;13465:18;13455:81;;13521:4;13513:6;13509:17;13499:27;;13455:81;13583:2;13575:6;13572:14;13552:18;13549:38;13546:84;;13602:18;;:::i;:::-;13546:84;13367:269;13316:320;;;:::o;13642:180::-;13690:77;13687:1;13680:88;13787:4;13784:1;13777:15;13811:4;13808:1;13801:15;13828:191;13868:4;13888:20;13906:1;13888:20;:::i;:::-;13883:25;;13922:20;13940:1;13922:20;:::i;:::-;13917:25;;13961:1;13958;13955:8;13952:34;;;13966:18;;:::i;:::-;13952:34;14011:1;14008;14004:9;13996:17;;13828:191;;;;:::o;14025:180::-;14073:77;14070:1;14063:88;14170:4;14167:1;14160:15;14194:4;14191:1;14184:15;14211:180;14259:77;14256:1;14249:88;14356:4;14353:1;14346:15;14380:4;14377:1;14370:15;14397:168;14480:11;14514:6;14509:3;14502:19;14554:4;14549:3;14545:14;14530:29;;14397:168;;;;:::o;14571:114::-;;:::o;14691:362::-;14832:3;14853:65;14916:1;14911:3;14853:65;:::i;:::-;14846:72;;14927:93;15016:3;14927:93;:::i;:::-;15045:1;15040:3;15036:11;15029:18;;14691:362;;;:::o;15059:748::-;15308:4;15346:3;15335:9;15331:19;15323:27;;15360:71;15428:1;15417:9;15413:17;15404:6;15360:71;:::i;:::-;15441:72;15509:2;15498:9;15494:18;15485:6;15441:72;:::i;:::-;15523;15591:2;15580:9;15576:18;15567:6;15523:72;:::i;:::-;15642:9;15636:4;15632:20;15627:2;15616:9;15612:18;15605:48;15670:130;15795:4;15670:130;:::i;:::-;15662:138;;15059:748;;;;;;:::o;15813:149::-;15849:7;15889:66;15882:5;15878:78;15867:89;;15813:149;;;:::o;15968:120::-;16040:23;16057:5;16040:23;:::i;:::-;16033:5;16030:34;16020:62;;16078:1;16075;16068:12;16020:62;15968:120;:::o;16094:141::-;16150:5;16181:6;16175:13;16166:22;;16197:32;16223:5;16197:32;:::i;:::-;16094:141;;;;:::o;16241:349::-;16310:6;16359:2;16347:9;16338:7;16334:23;16330:32;16327:119;;;16365:79;;:::i;:::-;16327:119;16485:1;16510:63;16565:7;16556:6;16545:9;16541:22;16510:63;:::i;:::-;16500:73;;16456:127;16241:349;;;;:::o;16618:301::-;16714:3;16735:70;16798:6;16793:3;16735:70;:::i;:::-;16728:77;;16815:43;16851:6;16846:3;16839:5;16815:43;:::i;:::-;16883:29;16905:6;16883:29;:::i;:::-;16878:3;16874:39;16867:46;;16618:301;;;;;:::o;16925:660::-;17130:4;17168:3;17157:9;17153:19;17145:27;;17182:71;17250:1;17239:9;17235:17;17226:6;17182:71;:::i;:::-;17263:72;17331:2;17320:9;17316:18;17307:6;17263:72;:::i;:::-;17345;17413:2;17402:9;17398:18;17389:6;17345:72;:::i;:::-;17464:9;17458:4;17454:20;17449:2;17438:9;17434:18;17427:48;17492:86;17573:4;17564:6;17556;17492:86;:::i;:::-;17484:94;;16925:660;;;;;;;;:::o;17591:148::-;17693:11;17730:3;17715:18;;17591:148;;;;:::o;17745:141::-;17794:4;17817:3;17809:11;;17840:3;17837:1;17830:14;17874:4;17871:1;17861:18;17853:26;;17745:141;;;:::o;17916:845::-;18019:3;18056:5;18050:12;18085:36;18111:9;18085:36;:::i;:::-;18137:89;18219:6;18214:3;18137:89;:::i;:::-;18130:96;;18257:1;18246:9;18242:17;18273:1;18268:137;;;;18419:1;18414:341;;;;18235:520;;18268:137;18352:4;18348:9;18337;18333:25;18328:3;18321:38;18388:6;18383:3;18379:16;18372:23;;18268:137;;18414:341;18481:38;18513:5;18481:38;:::i;:::-;18541:1;18555:154;18569:6;18566:1;18563:13;18555:154;;;18643:7;18637:14;18633:1;18628:3;18624:11;18617:35;18693:1;18684:7;18680:15;18669:26;;18591:4;18588:1;18584:12;18579:17;;18555:154;;;18738:6;18733:3;18729:16;18722:23;;18421:334;;18235:520;;18023:738;;17916:845;;;;:::o;18767:377::-;18873:3;18901:39;18934:5;18901:39;:::i;:::-;18956:89;19038:6;19033:3;18956:89;:::i;:::-;18949:96;;19054:52;19099:6;19094:3;19087:4;19080:5;19076:16;19054:52;:::i;:::-;19131:6;19126:3;19122:16;19115:23;;18877:267;18767:377;;;;:::o;19150:429::-;19327:3;19349:92;19437:3;19428:6;19349:92;:::i;:::-;19342:99;;19458:95;19549:3;19540:6;19458:95;:::i;:::-;19451:102;;19570:3;19563:10;;19150:429;;;;;:::o;19585:102::-;19627:8;19674:5;19671:1;19667:13;19646:34;;19585:102;;;:::o;19693:848::-;19754:5;19761:4;19785:6;19776:15;;19809:5;19800:14;;19823:712;19844:1;19834:8;19831:15;19823:712;;;19939:4;19934:3;19930:14;19924:4;19921:24;19918:50;;;19948:18;;:::i;:::-;19918:50;19998:1;19988:8;19984:16;19981:451;;;20413:4;20406:5;20402:16;20393:25;;19981:451;20463:4;20457;20453:15;20445:23;;20493:32;20516:8;20493:32;:::i;:::-;20481:44;;19823:712;;;19693:848;;;;;;;:::o;20547:1073::-;20601:5;20792:8;20782:40;;20813:1;20804:10;;20815:5;;20782:40;20841:4;20831:36;;20858:1;20849:10;;20860:5;;20831:36;20927:4;20975:1;20970:27;;;;21011:1;21006:191;;;;20920:277;;20970:27;20988:1;20979:10;;20990:5;;;21006:191;21051:3;21041:8;21038:17;21035:43;;;21058:18;;:::i;:::-;21035:43;21107:8;21104:1;21100:16;21091:25;;21142:3;21135:5;21132:14;21129:40;;;21149:18;;:::i;:::-;21129:40;21182:5;;;20920:277;;21306:2;21296:8;21293:16;21287:3;21281:4;21278:13;21274:36;21256:2;21246:8;21243:16;21238:2;21232:4;21229:12;21225:35;21209:111;21206:246;;;21362:8;21356:4;21352:19;21343:28;;21397:3;21390:5;21387:14;21384:40;;;21404:18;;:::i;:::-;21384:40;21437:5;;21206:246;21477:42;21515:3;21505:8;21499:4;21496:1;21477:42;:::i;:::-;21462:57;;;;21551:4;21546:3;21542:14;21535:5;21532:25;21529:51;;;21560:18;;:::i;:::-;21529:51;21609:4;21602:5;21598:16;21589:25;;20547:1073;;;;;;:::o;21626:281::-;21684:5;21708:23;21726:4;21708:23;:::i;:::-;21700:31;;21752:25;21768:8;21752:25;:::i;:::-;21740:37;;21796:104;21833:66;21823:8;21817:4;21796:104;:::i;:::-;21787:113;;21626:281;;;;:::o;21913:180::-;21961:77;21958:1;21951:88;22058:4;22055:1;22048:15;22082:4;22079:1;22072:15;22099:185;22139:1;22156:20;22174:1;22156:20;:::i;:::-;22151:25;;22190:20;22208:1;22190:20;:::i;:::-;22185:25;;22229:1;22219:35;;22234:18;;:::i;:::-;22219:35;22276:1;22273;22269:9;22264:14;;22099:185;;;;:::o;22290:233::-;22329:3;22352:24;22370:5;22352:24;:::i;:::-;22343:33;;22398:66;22391:5;22388:77;22385:103;;22468:18;;:::i;:::-;22385:103;22515:1;22508:5;22504:13;22497:20;;22290:233;;;:::o

Swarm Source

ipfs://078aea9a68930801b6356094dda7b694bb34594afc157cb4cc981b3b4654049d
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.