ETH Price: $3,297.45 (-1.26%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw184310072023-10-26 1:06:11812 days ago1698282371IN
0x4Da4b6B3...699698F24
0 ETH0.0023440424.65028871
Withdraw183759542023-10-18 8:08:23820 days ago1697616503IN
0x4Da4b6B3...699698F24
0 ETH0.000689297.24778734
Withdraw183242192023-10-11 2:26:35827 days ago1696991195IN
0x4Da4b6B3...699698F24
0 ETH0.000890949.36933852
Withdraw183077692023-10-08 19:13:35829 days ago1696792415IN
0x4Da4b6B3...699698F24
0 ETH0.000584756.14784612
Withdraw183052032023-10-08 10:35:23830 days ago1696761323IN
0x4Da4b6B3...699698F24
0 ETH0.000496836.36934259
Withdraw182877512023-10-06 0:01:35832 days ago1696550495IN
0x4Da4b6B3...699698F24
0 ETH0.000747937.863438
Withdraw182847772023-10-05 14:02:23833 days ago1696514543IN
0x4Da4b6B3...699698F24
0 ETH0.0016629817.48812878
Withdraw182750212023-10-04 5:18:35834 days ago1696396715IN
0x4Da4b6B3...699698F24
0 ETH0.00068186.07709634
Withdraw182637712023-10-02 15:33:59836 days ago1696260839IN
0x4Da4b6B3...699698F24
0 ETH0.0018824819.79143391
Withdraw182595702023-10-02 1:29:47836 days ago1696210187IN
0x4Da4b6B3...699698F24
0 ETH0.000596056.26818904
Withdraw182537032023-10-01 5:48:59837 days ago1696139339IN
0x4Da4b6B3...699698F24
0 ETH0.000563275.92276458
Withdraw182507012023-09-30 19:47:11837 days ago1696103231IN
0x4Da4b6B3...699698F24
0 ETH0.0008889611.39811413
Withdraw182505762023-09-30 19:22:11837 days ago1696101731IN
0x4Da4b6B3...699698F24
0 ETH0.0010989711.55406735
Withdraw182440842023-09-29 21:34:47838 days ago1696023287IN
0x4Da4b6B3...699698F24
0 ETH0.000941928.39658927
Withdraw182374122023-09-28 23:08:59839 days ago1695942539IN
0x4Da4b6B3...699698F24
0 ETH0.001364387.00035211
Withdraw182356792023-09-28 17:19:47840 days ago1695921587IN
0x4Da4b6B3...699698F24
0 ETH0.0017477618.37969438
Withdraw182331962023-09-28 8:58:59840 days ago1695891539IN
0x4Da4b6B3...699698F24
0 ETH0.000879759.25044156
Withdraw182285662023-09-27 17:24:47841 days ago1695835487IN
0x4Da4b6B3...699698F24
0 ETH0.0022379623.53474461
Withdraw182279432023-09-27 15:19:35841 days ago1695827975IN
0x4Da4b6B3...699698F24
0 ETH0.0018748519.71127418
Withdraw182252832023-09-27 6:22:11841 days ago1695795731IN
0x4Da4b6B3...699698F24
0 ETH0.0023454911.06348742
Withdraw182223142023-09-26 20:24:59841 days ago1695759899IN
0x4Da4b6B3...699698F24
0 ETH0.0015959916.78157119
Withdraw182221602023-09-26 19:53:59841 days ago1695758039IN
0x4Da4b6B3...699698F24
0 ETH0.0010514813.4799024
Withdraw182221172023-09-26 19:45:23841 days ago1695757523IN
0x4Da4b6B3...699698F24
0 ETH0.001272513.38184051
Withdraw182199012023-09-26 12:18:23842 days ago1695730703IN
0x4Da4b6B3...699698F24
0 ETH0.0010988711.5559607
Withdraw182189012023-09-26 8:56:11842 days ago1695718571IN
0x4Da4b6B3...699698F24
0 ETH0.0010519213.48556697
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer181876372023-09-21 23:51:11846 days ago1695340271
0x4Da4b6B3...699698F24
5.58703942 ETH
Transfer181872852023-09-21 22:40:23846 days ago1695336023
0x4Da4b6B3...699698F24
0.02690014 ETH
Transfer181870272023-09-21 21:48:47846 days ago1695332927
0x4Da4b6B3...699698F24
0.01413397 ETH
Transfer181869852023-09-21 21:40:23846 days ago1695332423
0x4Da4b6B3...699698F24
0.01858773 ETH
Transfer181868942023-09-21 21:21:47846 days ago1695331307
0x4Da4b6B3...699698F24
0.01644576 ETH
Transfer181868212023-09-21 21:06:59846 days ago1695330419
0x4Da4b6B3...699698F24
0.01250752 ETH
Transfer181868172023-09-21 21:06:11846 days ago1695330371
0x4Da4b6B3...699698F24
0.00709441 ETH
Transfer181867762023-09-21 20:57:47846 days ago1695329867
0x4Da4b6B3...699698F24
0.13904041 ETH
Transfer181865602023-09-21 20:13:59846 days ago1695327239
0x4Da4b6B3...699698F24
0.02722331 ETH
Transfer181864792023-09-21 19:57:47846 days ago1695326267
0x4Da4b6B3...699698F24
0.0318538 ETH
Transfer181864382023-09-21 19:49:35846 days ago1695325775
0x4Da4b6B3...699698F24
0.03180024 ETH
Transfer181864172023-09-21 19:45:23846 days ago1695325523
0x4Da4b6B3...699698F24
0.03422387 ETH
Transfer181864092023-09-21 19:43:47846 days ago1695325427
0x4Da4b6B3...699698F24
0.01780427 ETH
Transfer181864032023-09-21 19:42:35846 days ago1695325355
0x4Da4b6B3...699698F24
0.00510271 ETH
Transfer181863922023-09-21 19:40:23846 days ago1695325223
0x4Da4b6B3...699698F24
0.038725 ETH
Transfer181863832023-09-21 19:38:35846 days ago1695325115
0x4Da4b6B3...699698F24
0.02977045 ETH
Transfer181863792023-09-21 19:37:47846 days ago1695325067
0x4Da4b6B3...699698F24
0.01485096 ETH
Transfer181862712023-09-21 19:15:47846 days ago1695323747
0x4Da4b6B3...699698F24
0.09697494 ETH
Transfer181860042023-09-21 18:22:11847 days ago1695320531
0x4Da4b6B3...699698F24
0.01727587 ETH
Transfer181859892023-09-21 18:19:11847 days ago1695320351
0x4Da4b6B3...699698F24
0.07985008 ETH
Transfer181858382023-09-21 17:48:59847 days ago1695318539
0x4Da4b6B3...699698F24
0.01310562 ETH
Transfer181858252023-09-21 17:46:23847 days ago1695318383
0x4Da4b6B3...699698F24
0.01420606 ETH
Transfer181857332023-09-21 17:27:59847 days ago1695317279
0x4Da4b6B3...699698F24
0.02124173 ETH
Transfer181856372023-09-21 17:08:35847 days ago1695316115
0x4Da4b6B3...699698F24
0.01353798 ETH
Transfer181856062023-09-21 17:02:11847 days ago1695315731
0x4Da4b6B3...699698F24
0.04796158 ETH
View All Internal Transactions
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RavenFundStakingV2

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at Etherscan.io on 2023-09-02
*/

// File: @openzeppelin/contracts/utils/math/SignedMath.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @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 up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (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; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                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.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 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.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            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 (rounding == Rounding.Up && 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 down.
     *
     * 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;



/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @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), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(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) {
        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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        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 keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

// File: @unlock-protocol/contracts/dist/PublicLock/IPublicLockV13.sol


pragma solidity >=0.5.17 <0.9.0;
pragma experimental ABIEncoderV2;

/**
 * @title The PublicLock Interface
 */

interface IPublicLockV13 {
  /// Functions
  function initialize(
    address _lockCreator,
    uint _expirationDuration,
    address _tokenAddress,
    uint _keyPrice,
    uint _maxNumberOfKeys,
    string calldata _lockName
  ) external;

  // default role from OpenZeppelin
  function DEFAULT_ADMIN_ROLE()
    external
    view
    returns (bytes32 role);

  /**
   * @notice The version number of the current implementation on this network.
   * @return The current version number.
   */
  function publicLockVersion()
    external
    pure
    returns (uint16);

  /**
   * @dev Called by lock manager to withdraw all funds from the lock
   * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually
   * the same as `tokenAddress` in MixinFunds.
   * @param _recipient specifies the address that will receive the tokens
   * @param _amount specifies the max amount to withdraw, which may be reduced when
   * considering the available balance. Set to 0 or MAX_UINT to withdraw everything.
   * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` use cases.
   */
  function withdraw(
    address _tokenAddress,
    address payable _recipient,
    uint _amount
  ) external;

  /**
   * A function which lets a Lock manager of the lock to change the price for future purchases.
   * @dev Throws if called by other than a Lock manager
   * @dev Throws if lock has been disabled
   * @dev Throws if _tokenAddress is not a valid token
   * @param _keyPrice The new price to set for keys
   * @param _tokenAddress The address of the erc20 token to use for pricing the keys,
   * or 0 to use ETH
   */
  function updateKeyPricing(
    uint _keyPrice,
    address _tokenAddress
  ) external;

  /**
   * Update the main key properties for the entire lock:
   *
   * - default duration of each key
   * - the maximum number of keys the lock can edit
   * - the maximum number of keys a single address can hold
   *
   * @notice keys previously bought are unaffected by this changes in expiration duration (i.e.
   * existing keys timestamps are not recalculated/updated)
   * @param _newExpirationDuration the new amount of time for each key purchased or type(uint).max for a non-expiring key
   * @param _maxKeysPerAcccount the maximum amount of key a single user can own
   * @param _maxNumberOfKeys uint the maximum number of keys
   * @dev _maxNumberOfKeys Can't be smaller than the existing supply
   */
  function updateLockConfig(
    uint _newExpirationDuration,
    uint _maxNumberOfKeys,
    uint _maxKeysPerAcccount
  ) external;

  /**
   * Checks if the user has a non-expired key.
   * @param _user The address of the key owner
   */
  function getHasValidKey(
    address _user
  ) external view returns (bool);

  /**
   * @dev Returns the key's ExpirationTimestamp field for a given owner.
   * @param _tokenId the id of the key
   * @dev Returns 0 if the owner has never owned a key for this lock
   */
  function keyExpirationTimestampFor(
    uint _tokenId
  ) external view returns (uint timestamp);

  /**
   * Public function which returns the total number of unique owners (both expired
   * and valid).  This may be larger than totalSupply.
   */
  function numberOfOwners() external view returns (uint);

  /**
   * Allows the Lock owner to assign
   * @param _lockName a descriptive name for this Lock.
   * @param _lockSymbol a Symbol for this Lock (default to KEY).
   * @param _baseTokenURI the baseTokenURI for this Lock
   */
  function setLockMetadata(
    string calldata _lockName,
    string calldata _lockSymbol,
    string calldata _baseTokenURI
  ) external;

  /**
   * @dev Gets the token symbol
   * @return string representing the token symbol
   */
  function symbol() external view returns (string memory);

  /**  @notice A distinct Uniform Resource Identifier (URI) for a given asset.
   * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
   *  3986. The URI may point to a JSON file that conforms to the "ERC721
   *  Metadata JSON Schema".
   * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
   * @param _tokenId The tokenID we're inquiring about
   * @return String representing the URI for the requested token
   */
  function tokenURI(
    uint256 _tokenId
  ) external view returns (string memory);

  /**
   * Allows a Lock manager to add or remove an event hook
   * @param _onKeyPurchaseHook Hook called when the `purchase` function is called
   * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called
   * @param _onValidKeyHook Hook called to determine if the contract should overide the status for a given address
   * @param _onTokenURIHook Hook called to generate a data URI used for NFT metadata
   * @param _onKeyTransferHook Hook called when a key is transfered
   * @param _onKeyExtendHook Hook called when a key is extended or renewed
   * @param _onKeyGrantHook Hook called when a key is granted
   */
  function setEventHooks(
    address _onKeyPurchaseHook,
    address _onKeyCancelHook,
    address _onValidKeyHook,
    address _onTokenURIHook,
    address _onKeyTransferHook,
    address _onKeyExtendHook,
    address _onKeyGrantHook
  ) external;

  /**
   * Allows a Lock manager to give a collection of users a key with no charge.
   * Each key may be assigned a different expiration date.
   * @dev Throws if called by other than a Lock manager
   * @param _recipients An array of receiving addresses
   * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted
   * @return the ids of the granted tokens
   */
  function grantKeys(
    address[] calldata _recipients,
    uint[] calldata _expirationTimestamps,
    address[] calldata _keyManagers
  ) external returns (uint256[] memory);

  /**
   * Allows the Lock owner to extend an existing keys with no charge.
   * @param _tokenId The id of the token to extend
   * @param _duration The duration in secondes to add ot the key
   * @dev set `_duration` to 0 to use the default duration of the lock
   */
  function grantKeyExtension(
    uint _tokenId,
    uint _duration
  ) external;

  /**
   * @dev Purchase function
   * @param _values array of tokens amount to pay for this purchase >= the current keyPrice - any applicable discount
   * (_values is ignored when using ETH)
   * @param _recipients array of addresses of the recipients of the purchased key
   * @param _referrers array of addresses of the users making the referral
   * @param _keyManagers optional array of addresses to grant managing rights to a specific address on creation
   * @param _data array of arbitrary data populated by the front-end which initiated the sale
   * @notice when called for an existing and non-expired key, the `_keyManager` param will be ignored
   * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the
   * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more
   * than keyPrice is approved for spending).
   * @return tokenIds the ids of the created tokens
   */
  function purchase(
    uint256[] calldata _values,
    address[] calldata _recipients,
    address[] calldata _referrers,
    address[] calldata _keyManagers,
    bytes[] calldata _data
  ) external payable returns (uint256[] memory tokenIds);

  /**
   * @dev Extend function
   * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount
   * (_value is ignored when using ETH)
   * @param _tokenId the id of the key to extend
   * @param _referrer address of the user making the referral
   * @param _data arbitrary data populated by the front-end which initiated the sale
   * @dev Throws if lock is disabled or key does not exist for _recipient. Throws if _recipient == address(0).
   */
  function extend(
    uint _value,
    uint _tokenId,
    address _referrer,
    bytes calldata _data
  ) external payable;

  /**
   * Returns the percentage of the keyPrice to be sent to the referrer (in basis points)
   * @param _referrer the address of the referrer
   * @return referrerFee the percentage of the keyPrice to be sent to the referrer (in basis points)
   */
  function referrerFees(
    address _referrer
  ) external view returns (uint referrerFee);

  /**
   * Set a specific percentage of the keyPrice to be sent to the referrer while purchasing,
   * extending or renewing a key.
   * @param _referrer the address of the referrer
   * @param _feeBasisPoint the percentage of the price to be used for this
   * specific referrer (in basis points)
   * @dev To send a fixed percentage of the key price to all referrers, sett a percentage to `address(0)`
   */
  function setReferrerFee(
    address _referrer,
    uint _feeBasisPoint
  ) external;

  /**
   * Merge existing keys
   * @param _tokenIdFrom the id of the token to substract time from
   * @param _tokenIdTo the id of the destination token  to add time
   * @param _amount the amount of time to transfer (in seconds)
   */
  function mergeKeys(
    uint _tokenIdFrom,
    uint _tokenIdTo,
    uint _amount
  ) external;

  /**
   * Deactivate an existing key
   * @param _tokenId the id of token to burn
   * @notice the key will be expired and ownership records will be destroyed
   */
  function burn(uint _tokenId) external;

  /**
   * @param _gasRefundValue price in wei or token in smallest price unit
   * @dev Set the value to be refunded to the sender on purchase
   */
  function setGasRefundValue(
    uint256 _gasRefundValue
  ) external;

  /**
   * _gasRefundValue price in wei or token in smallest price unit
   * @dev Returns the value/price to be refunded to the sender on purchase
   */
  function gasRefundValue()
    external
    view
    returns (uint256 _gasRefundValue);

  /**
   * @notice returns the minimum price paid for a purchase with these params.
   * @dev this considers any discount from Unlock or the OnKeyPurchase hook.
   */
  function purchasePriceFor(
    address _recipient,
    address _referrer,
    bytes calldata _data
  ) external view returns (uint);

  /**
   * Allow a Lock manager to change the transfer fee.
   * @dev Throws if called by other than a Lock manager
   * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps).
   * Ex: 200 bps = 2%
   */
  function updateTransferFee(
    uint _transferFeeBasisPoints
  ) external;

  /**
   * Determines how much of a fee would need to be paid in order to
   * transfer to another account.  This is pro-rated so the fee goes
   * down overtime.
   * @dev Throws if _tokenId does not have a valid key
   * @param _tokenId The id of the key check the transfer fee for.
   * @param _time The amount of time to calculate the fee for.
   * @return The transfer fee in seconds.
   */
  function getTransferFee(
    uint _tokenId,
    uint _time
  ) external view returns (uint);

  /**
   * @dev Invoked by a Lock manager to expire the user's key
   * and perform a refund and cancellation of the key
   * @param _tokenId The key id we wish to refund to
   * @param _amount The amount to refund to the key-owner
   * @dev Throws if called by other than a Lock manager
   * @dev Throws if _keyOwner does not have a valid key
   */
  function expireAndRefundFor(
    uint _tokenId,
    uint _amount
  ) external;

  /**
   * @dev allows the key manager to expire a given tokenId
   * and send a refund to the keyOwner based on the amount of time remaining.
   * @param _tokenId The id of the key to cancel.
   * @notice cancel is enabled with a 10% penalty by default on all Locks.
   */
  function cancelAndRefund(uint _tokenId) external;

  /**
   * Allow a Lock manager to change the refund penalty.
   * @dev Throws if called by other than a Lock manager
   * @param _freeTrialLength The new duration of free trials for this lock
   * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps)
   */
  function updateRefundPenalty(
    uint _freeTrialLength,
    uint _refundPenaltyBasisPoints
  ) external;

  /**
   * @dev Determines how much of a refund a key owner would receive if they issued
   * @param _tokenId the id of the token to get the refund value for.
   * @notice Due to the time required to mine a tx, the actual refund amount will be lower
   * than what the user reads from this call.
   * @return refund the amount of tokens refunded
   */
  function getCancelAndRefundValue(
    uint _tokenId
  ) external view returns (uint refund);

  function addLockManager(address account) external;

  function isLockManager(
    address account
  ) external view returns (bool);

  /**
   * Returns the address of the `onKeyPurchaseHook` hook.
   * @return hookAddress address of the hook
   */
  function onKeyPurchaseHook()
    external
    view
    returns (address hookAddress);

  /**
   * Returns the address of the `onKeyCancelHook` hook.
   * @return hookAddress address of the hook
   */
  function onKeyCancelHook()
    external
    view
    returns (address hookAddress);

  /**
   * Returns the address of the `onValidKeyHook` hook.
   * @return hookAddress address of the hook
   */
  function onValidKeyHook()
    external
    view
    returns (address hookAddress);

  /**
   * Returns the address of the `onTokenURIHook` hook.
   * @return hookAddress address of the hook
   */
  function onTokenURIHook()
    external
    view
    returns (address hookAddress);

  /**
   * Returns the address of the `onKeyTransferHook` hook.
   * @return hookAddress address of the hook
   */
  function onKeyTransferHook()
    external
    view
    returns (address hookAddress);

  /**
   * Returns the address of the `onKeyExtendHook` hook.
   * @return hookAddress the address ok the hook
   */
  function onKeyExtendHook()
    external
    view
    returns (address hookAddress);

  /**
   * Returns the address of the `onKeyGrantHook` hook.
   * @return hookAddress the address ok the hook
   */
  function onKeyGrantHook()
    external
    view
    returns (address hookAddress);

  function renounceLockManager() external;

  /**
   * @return the maximum number of key allowed for a single address
   */
  function maxKeysPerAddress() external view returns (uint);

  function expirationDuration()
    external
    view
    returns (uint256);

  function freeTrialLength()
    external
    view
    returns (uint256);

  function keyPrice() external view returns (uint256);

  function maxNumberOfKeys()
    external
    view
    returns (uint256);

  function refundPenaltyBasisPoints()
    external
    view
    returns (uint256);

  function tokenAddress() external view returns (address);

  function transferFeeBasisPoints()
    external
    view
    returns (uint256);

  function unlockProtocol() external view returns (address);

  function keyManagerOf(
    uint
  ) external view returns (address);

  ///===================================================================

  /**
   * @notice Allows the key owner to safely share their key (parent key) by
   * transferring a portion of the remaining time to a new key (child key).
   * @dev Throws if key is not valid.
   * @dev Throws if `_to` is the zero address
   * @param _to The recipient of the shared key
   * @param _tokenId the key to share
   * @param _timeShared The amount of time shared
   * checks if `_to` is a smart contract (code size > 0). If so, it calls
   * `onERC721Received` on `_to` and throws if the return value is not
   * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`.
   * @dev Emit Transfer event
   */
  function shareKey(
    address _to,
    uint _tokenId,
    uint _timeShared
  ) external;

  /**
   * @notice Update transfer and cancel rights for a given key
   * @param _tokenId The id of the key to assign rights for
   * @param _keyManager The address to assign the rights to for the given key
   */
  function setKeyManagerOf(
    uint _tokenId,
    address _keyManager
  ) external;

  /**
   * Check if a certain key is valid
   * @param _tokenId the id of the key to check validity
   * @notice this makes use of the onValidKeyHook if it is set
   */
  function isValidKey(
    uint _tokenId
  ) external view returns (bool);

  /**
   * Returns the number of keys owned by `_keyOwner` (expired or not)
   * @param _keyOwner address for which we are retrieving the total number of keys
   * @return numberOfKeys total number of keys owned by the address
   */
  function totalKeys(
    address _keyOwner
  ) external view returns (uint numberOfKeys);

  /// @notice A descriptive name for a collection of NFTs in this contract
  function name()
    external
    view
    returns (string memory _name);

  ///===================================================================

  /// From ERC165.sol
  function supportsInterface(
    bytes4 interfaceId
  ) external view returns (bool);

  ///===================================================================

  /// From ERC-721
  /**
   * In the specific case of a Lock, `balanceOf` returns only the tokens with a valid expiration timerange
   * @return balance The number of valid keys owned by `_keyOwner`
   */
  function balanceOf(
    address _owner
  ) external view returns (uint256 balance);

  /**
   * @dev Returns the owner of the NFT specified by `tokenId`.
   */
  function ownerOf(
    uint256 tokenId
  ) external view returns (address _owner);

  /**
   * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
   * another (`to`).
   *
   * Requirements:
   * - `from`, `to` cannot be zero.
   * - `tokenId` must be owned by `from`.
   * - If the caller is not `from`, it must be have been allowed to move this
   * NFT by either {approve} or {setApprovalForAll}.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId
  ) external;

  /**
   * an ERC721-like function to transfer a token from one account to another.
   * @param from the owner of token to transfer
   * @param to the address that will receive the token
   * @param tokenId the id of the token
   * @dev Requirements: if the caller is not `from`, it must be approved to move this token by
   * either {approve} or {setApprovalForAll}.
   * The key manager will be reset to address zero after the transfer
   */
  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  ) external;

  /**
   * Lending a key allows you to transfer the token while retaining the
   * ownerships right by setting yourself as a key manager first.
   * @param from the owner of token to transfer
   * @param to the address that will receive the token
   * @param tokenId the id of the token
   * @notice This function can only be called by 1) the key owner when no key manager is set or 2) the key manager.
   * After calling the function, the `_recipent` will be the new owner, and the sender of the tx
   * will become the key manager.
   */
  function lendKey(
    address from,
    address to,
    uint tokenId
  ) external;

  /**
   * Unlend is called when you have lent a key and want to claim its full ownership back.
   * @param _recipient the address that will receive the token ownership
   * @param _tokenId the id of the token
   * @dev Only the key manager of the token can call this function
   */
  function unlendKey(
    address _recipient,
    uint _tokenId
  ) external;

  function approve(address to, uint256 tokenId) external;

  /**
   * @notice Get the approved address for a single NFT
   * @dev Throws if `_tokenId` is not a valid NFT.
   * @param _tokenId The NFT to find the approved address for
   * @return operator The approved address for this NFT, or the zero address if there is none
   */
  function getApproved(
    uint256 _tokenId
  ) external view returns (address operator);

  /**
   * @dev Sets or unsets the approval of a given operator
   * An operator is allowed to transfer all tokens of the sender on their behalf
   * @param _operator operator address to set the approval
   * @param _approved representing the status of the approval to be set
   * @notice disabled when transfers are disabled
   */
  function setApprovalForAll(
    address _operator,
    bool _approved
  ) external;

  /**
   * @dev Tells whether an operator is approved by a given keyManager
   * @param _owner owner address which you want to query the approval of
   * @param _operator operator address which you want to query the approval of
   * @return bool whether the given operator is approved by the given owner
   */
  function isApprovedForAll(
    address _owner,
    address _operator
  ) external view returns (bool);

  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes calldata data
  ) external;

  /**
   * Returns the total number of keys, including non-valid ones
   * @return _totalKeysCreated the total number of keys, valid or not
   */
  function totalSupply() external view returns (uint256 _totalKeysCreated);

  function tokenOfOwnerByIndex(
    address _owner,
    uint256 index
  ) external view returns (uint256 tokenId);

  function tokenByIndex(
    uint256 index
  ) external view returns (uint256);

  /**
   * Innherited from Open Zeppelin AccessControl.sol
   */
  function getRoleAdmin(
    bytes32 role
  ) external view returns (bytes32);

  function grantRole(
    bytes32 role,
    address account
  ) external;

  function revokeRole(
    bytes32 role,
    address account
  ) external;

  function renounceRole(
    bytes32 role,
    address account
  ) external;

  function hasRole(
    bytes32 role,
    address account
  ) external view returns (bool);

  /** `owner()` is provided as an helper to mimick the `Ownable` contract ABI.
   * The `Ownable` logic is used by many 3rd party services to determine
   * contract ownership - e.g. who is allowed to edit metadata on Opensea.
   *
   * @notice This logic is NOT used internally by the Unlock Protocol and is made
   * available only as a convenience helper.
   */
  function owner() external view returns (address owner);

  function setOwner(address account) external;

  function isOwner(
    address account
  ) external view returns (bool isOwner);

  /**
   * Migrate data from the previous single owner => key mapping to
   * the new data structure w multiple tokens.
   * @param _calldata an ABI-encoded representation of the params (v10: the number of records to migrate as `uint`)
   * @dev when all record schemas are sucessfully upgraded, this function will update the `schemaVersion`
   * variable to the latest/current lock version
   */
  function migrate(bytes calldata _calldata) external;

  /**
   * Returns the version number of the data schema currently used by the lock
   * @notice if this is different from `publicLockVersion`, then the ability to purchase, grant
   * or extend keys is disabled.
   * @dev will return 0 if no ;igration has ever been run
   */
  function schemaVersion() external view returns (uint);

  /**
   * Set the schema version to the latest
   * @notice only lock manager call call this
   */
  function updateSchemaVersion() external;

  /**
   * Renew a given token
   * @notice only works for non-free, expiring, ERC20 locks
   * @param _tokenId the ID fo the token to renew
   * @param _referrer the address of the person to be granted UDT
   */
  function renewMembershipFor(
    uint _tokenId,
    address _referrer
  ) external;

  /**
   * @dev helper to check if a key is currently renewable 
   * it will revert if the pricing or duration of the lock have been modified 
   * unfavorably since the key was bought(price increase or duration decrease).
   * It will also revert if a lock is not renewable or if the key is not ready for renewal yet 
   * (at least 90% expired).
   * @param tokenId the id of the token to check
   * @param referrer the address where to send the referrer fee
   * @return true if the terms has changed
   */
  function isRenewable(uint256 tokenId, address referrer) external view returns (bool);
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    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.
     *
     * _Available since v3.4._
     */
    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.
     *
     * _Available since v3.4._
     */
    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.
     *
     * _Available since v3.4._
     */
    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.
     *
     * _Available since v3.4._
     */
    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 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) {
        return a + b;
    }

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

    /**
     * @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) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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 a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting 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) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

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

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

// File: contracts/RFStakePoolV2.sol



// RavenFund - $RAVEN
//
// The raven symbolizes prophecy, insight, transformation, and intelligence. It also represents long-term success.
// The 1st AI-powered hedge fund
//
// https://www.ravenfund.app/
// https://twitter.com/RavenFund
// https://t.me/RavenFundPortal

pragma solidity ^0.8.19;







interface IRavenFundStaking {
    function stakingToken() external view returns (IERC20);
    function rewardsProvider() external view returns (address);
    function teamWallet() external view returns (address);
    function owner() external view returns (address);
    function lockSubNFT(uint256 _index) external view returns (IPublicLockV13, IERC721);
    function maxStakeAmount() external view returns (uint256);
    function minClaimAmount() external view returns (uint256);
    function stakeWaitTime() external view returns (uint256);
    function claimInterval() external view returns (uint256);
    function timeElapsedFactor() external view returns (uint256);
    function rewardResetInterval() external view returns (uint256);
    function malusNoSubscription() external view returns (uint256);
    function totalDistributed() external view returns (uint256);
    function enableClaim() external view returns (bool);
    function enableStake() external view returns (bool);
    function activateSendTeam() external view returns (bool);
    function totalStakedAmount() external view returns (uint256);
    function fundDeposits(uint256 _index) external view returns (uint256, uint256);
    function consolidatedFunds() external view returns (uint256);
    function stakers(address _address) external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256);
    function stakerAddresses(uint256 _index) external view returns (address);
}

contract RavenFundStakingV2 is ReentrancyGuard {
    using SafeMath for uint256;

    IRavenFundStaking public ravenFundStakingV1;
    address public ravenFundStakingOldAddress;
    IERC20 public stakingToken;
    address public rewardsProvider;
    address public teamWallet;
    address public owner;
    Lockers[] public lockSubNFT;

    struct Lockers {
        IPublicLockV13 instance;
        IERC721 nft;
    }

    uint256 public maxStakeAmount = 0;
    uint256 public minClaimAmount = 15_000 ether;
    uint256 public stakeWaitTime = 12 hours;
    uint256 public claimInterval = 24 hours;
    uint256 public timeElapsedFactor = 7 days;
    uint256 public rewardResetInterval = 15 days;
    uint256 public malusNoSubscription = 70;
    uint256 public totalDistributed = 0;

    bool public enableClaim = false;
    bool public enableStake = false;
    bool public activateSendTeam = true;
    bool public activateConsolidate = true;
    bool public activateRestore = true;

    struct StakerInfo {
        uint256 amountStaked;
        uint256 lastStakeTime;
        uint256 lastClaimTime;
        uint256 rewardsEarned;
        uint256 rewardsClaimed;
        uint256 lastRewardUpdateTime;
        uint256 keyArray;
        bool restoring;
    }

    uint256 public totalStakedAmount;

    struct Funds {
        uint256 amount;
        uint256 depositTime;
    }

    Funds[] public fundDeposits;
    uint256 public consolidatedFunds = 0;

    mapping(address => StakerInfo) public stakers;
    address[] public stakerAddresses;

    constructor(address _stakingToken, address _rewardsProvider, address _teamWallet) {
        stakingToken = IERC20(_stakingToken);
        rewardsProvider = _rewardsProvider;
        teamWallet = _teamWallet;
        owner = msg.sender;
        ravenFundStakingV1 = IRavenFundStaking(address(0xeb94e7cD446a15DCab9C5d04dc5Bb805E528DCbb));
    }

    modifier onlyRewardsProvider() {
        require(msg.sender == rewardsProvider || msg.sender == owner || msg.sender == teamWallet, "Not the rewards provider");
        _;
    }

    function stake(uint256 amount) external nonReentrant {
        require(enableStake, "Stake not enabled.");
        (uint256 amountStaked, uint256 lastStakeTime, uint256 lastClaimTime, uint256 rewardsEarned, uint256 rewardsClaimed, uint256 lastRewardUpdateTime, uint256 keyArray) = ravenFundStakingV1.stakers(msg.sender);
        require(amountStaked <= 0, "Restore your token to the new contract before");
        StakerInfo storage staker = stakers[msg.sender];
        require(staker.restoring == false, "Finish restore before stake again");
        if (maxStakeAmount > 0) {
            require(staker.amountStaked + amount <= maxStakeAmount, "Max stake amount reached");
        }

        if (staker.lastRewardUpdateTime == 0) {
            staker.lastRewardUpdateTime = block.timestamp;
        }

        if (staker.keyArray == 0){
            stakerAddresses.push(msg.sender);
            staker.keyArray = stakerAddresses.length;
        }

        uint256 allowance = stakingToken.allowance(msg.sender, address(this));
        require(allowance >= amount, "Allowance is not sufficient to stake tokens");

        staker.lastStakeTime = block.timestamp;
        staker.amountStaked = staker.amountStaked.add(amount);
        totalStakedAmount = totalStakedAmount.add(amount);

        require(stakingToken.transferFrom(msg.sender, address(this), amount), "Token transfer failed");
    }

    function withdraw(uint256 amount) external nonReentrant {
        StakerInfo storage staker = stakers[msg.sender];

        require(amount > 0, "Amount must be greater than 0");
        require(staker.amountStaked >= amount, "Insufficient staked amount");

        staker.amountStaked = staker.amountStaked.sub(amount);
        totalStakedAmount = totalStakedAmount.sub(amount);

        if (staker.amountStaked <= 0) {
            uint256 reward = staker.rewardsEarned;
            staker.rewardsEarned = 0;
            staker.lastClaimTime = block.timestamp;
            uint256 contractBalance = address(this).balance;
            if (reward > 0 && contractBalance >= reward && activateSendTeam){
                calibrateFundArray(reward);

                payable(teamWallet).transfer(reward);
            }
        }

        require(stakingToken.transfer(msg.sender, amount), "Token transfer failed");
    }

    function canRestore(address stakerAddress) public view returns (bool) {
        (uint256 amountStaked, uint256 lastStakeTime, uint256 lastClaimTime, uint256 rewardsEarned, uint256 rewardsClaimed, uint256 lastRewardUpdateTime, uint256 keyArray) = ravenFundStakingV1.stakers(stakerAddress);
        if (amountStaked > 0)
        {
            StakerInfo storage staker = stakers[stakerAddress];
            if (staker.amountStaked <= 0)
            {
                return true;
            }
        }
        return false;
    }

    function restoreStep1() external nonReentrant {
        require(canRestore(msg.sender), "You cannot restore data");
        require(activateRestore, "You cannot restore data");
        (uint256 amountStaked, uint256 lastStakeTime, uint256 lastClaimTime, uint256 rewardsEarned, uint256 rewardsClaimed, uint256 lastRewardUpdateTime, uint256 keyArray) = ravenFundStakingV1.stakers(msg.sender);

        stakers[msg.sender] = StakerInfo(amountStaked, lastStakeTime, lastClaimTime, rewardsEarned, rewardsClaimed, lastRewardUpdateTime, keyArray, true);
        stakerAddresses.push(msg.sender);
        stakers[msg.sender].keyArray = stakerAddresses.length;

        //withdraw with contract old
    }

    function restoreStep2() external nonReentrant {
        // after withdraw with contract old
        StakerInfo storage staker = stakers[msg.sender];
        require(staker.amountStaked > 0, "Nothing to restore");
        require(staker.restoring, "Not in restore mode");

        uint256 allowance = stakingToken.allowance(msg.sender, address(this));
        require(allowance >= staker.amountStaked, "Allowance is not sufficient to stake tokens");

        require(stakingToken.transferFrom(msg.sender, address(this), staker.amountStaked), "Token transfer failed");

        staker.restoring = false;
        totalStakedAmount = totalStakedAmount.add(staker.amountStaked);
    }

    function canClaim(address stakerAddress) public view returns (bool) {
        StakerInfo storage staker = stakers[stakerAddress];
        uint256 reward = previewStakerRewards(stakerAddress);
        uint256 contractBalance = address(this).balance;
        return enableClaim && reward > 0 && contractBalance >= reward && (staker.amountStaked >= minClaimAmount) && (block.timestamp > staker.lastStakeTime + stakeWaitTime) && (block.timestamp > staker.lastClaimTime + claimInterval);
    }

    function reasonClaim(address stakerAddress) public view returns (string memory) {
        StakerInfo storage staker = stakers[stakerAddress];
        uint256 reward = previewStakerRewards(stakerAddress);
        uint256 contractBalance = address(this).balance;
        if (!enableClaim){
            return "Claim not enabled, please wait a moment.";
        }
        if (staker.amountStaked < minClaimAmount) {
            return string(abi.encodePacked("To be eligible, you have to stake a minimum $RAVEN of ", Strings.toString(minClaimAmount.div(1 ether))));
        }
        if (block.timestamp <= staker.lastStakeTime + stakeWaitTime) {
            return Strings.toString(staker.lastStakeTime + stakeWaitTime);
        }
        if (block.timestamp <= staker.lastClaimTime + claimInterval) {
            return Strings.toString(staker.lastClaimTime + claimInterval);
        }
        if (reward <= 0){
            return "You don't have any reward to claim for the moment.";
        }
        if (contractBalance < reward) {
            return "Please wait new funds to claim your reward.";
        }
        return "You can claim !";
    }

    function claim() external nonReentrant {
        require(enableClaim, "Claim not enabled.");
        StakerInfo storage staker = stakers[msg.sender];
        require(staker.amountStaked >= minClaimAmount, "Not enough tokens staked to claim.");
        require(block.timestamp > staker.lastStakeTime + stakeWaitTime, "Need to wait after staking");
        require(block.timestamp > staker.lastClaimTime + claimInterval, "Already claimed recently");

        updateStakerRewards(msg.sender);

        uint256 reward = staker.rewardsEarned;
        require(reward > 0, "No rewards available");

        uint256 contractBalance = address(this).balance;
        require(contractBalance >= reward, "Not enough ETH in the contract");

        calibrateFundArray(reward);
        staker.rewardsEarned = 0;
        staker.lastClaimTime = block.timestamp;
        staker.rewardsClaimed = staker.rewardsClaimed.add(reward);
        totalDistributed = totalDistributed.add(reward);

        payable(msg.sender).transfer(reward);
    }

    function previewStakerRewards(address stakerAddress) public view returns (uint256) {
        StakerInfo storage staker = stakers[stakerAddress];

        if (staker.amountStaked < minClaimAmount || totalStakedAmount <= 0 || timeElapsedFactor <= 0) {
            return staker.rewardsEarned;
        }

        uint256 totalReward = 0;
        for(uint256 i = 0; i < fundDeposits.length; i++) {
            if (fundDeposits[i].amount == 0) {
                continue;
            }
            uint256 referenceTime = max(staker.lastRewardUpdateTime, fundDeposits[i].depositTime);
            uint256 timeElapsed = block.timestamp.sub(referenceTime);
            
            uint256 timeFactor;
            if(timeElapsed >= timeElapsedFactor) {
                timeFactor = 1 ether;
            } else {
                timeFactor = timeElapsed.mul(1 ether).div(timeElapsedFactor);
            }
            
            uint256 stakerShare = staker.amountStaked.mul(1 ether).div(totalStakedAmount);
            uint256 rewardFromThisDeposit = fundDeposits[i].amount.mul(stakerShare).div(1 ether);
            rewardFromThisDeposit = rewardFromThisDeposit.mul(timeFactor).div(1 ether);

            if (!ownsActiveNFT(stakerAddress)) {
                rewardFromThisDeposit = rewardFromThisDeposit.mul(malusNoSubscription).div(100);
            }

            totalReward = totalReward.add(rewardFromThisDeposit);
        }
        // Then add rewards from consolidated funds
        uint256 timeElapsedConsolidated = block.timestamp.sub(staker.lastRewardUpdateTime);
        uint256 timeFactorConsolidated;
        if(timeElapsedConsolidated >= timeElapsedFactor) {
            timeFactorConsolidated = 1 ether;
        } else {
            timeFactorConsolidated = timeElapsedConsolidated.mul(1 ether).div(timeElapsedFactor);
        }
        uint256 stakerShareFromConsolidated = staker.amountStaked.mul(1 ether).div(totalStakedAmount);
        uint256 rewardFromConsolidated = consolidatedFunds.mul(stakerShareFromConsolidated).div(1 ether);
        rewardFromConsolidated = rewardFromConsolidated.mul(timeFactorConsolidated).div(1 ether);
        if (!ownsActiveNFT(stakerAddress)) {
            rewardFromConsolidated = rewardFromConsolidated.mul(malusNoSubscription).div(100);
        }

        totalReward = totalReward.add(rewardFromConsolidated);

        return staker.rewardsEarned.add(totalReward);
    }

    function updateStakerRewards(address stakerAddress) internal {
        StakerInfo storage staker = stakers[stakerAddress];

        if (staker.amountStaked < minClaimAmount || totalStakedAmount <= 0 || timeElapsedFactor <= 0) {
            staker.lastRewardUpdateTime = block.timestamp;
            return;
        }

        uint256 totalReward = 0;
        for(uint256 i = 0; i < fundDeposits.length; i++) {
            if (fundDeposits[i].amount == 0) {
                continue;
            }
            uint256 referenceTime = max(staker.lastRewardUpdateTime, fundDeposits[i].depositTime);
            uint256 timeElapsed = block.timestamp.sub(referenceTime);
            
            uint256 timeFactor;
            if(timeElapsed >= timeElapsedFactor) {
                timeFactor = 1 ether;
            } else {
                timeFactor = timeElapsed.mul(1 ether).div(timeElapsedFactor);
            }
            
            uint256 stakerShare = staker.amountStaked.mul(1 ether).div(totalStakedAmount);
            uint256 rewardFromThisDeposit = fundDeposits[i].amount.mul(stakerShare).div(1 ether);
            rewardFromThisDeposit = rewardFromThisDeposit.mul(timeFactor).div(1 ether);

            if (!ownsActiveNFT(stakerAddress)) {
                rewardFromThisDeposit = rewardFromThisDeposit.mul(malusNoSubscription).div(100);
            }

            totalReward = totalReward.add(rewardFromThisDeposit);
        }
        // Then add rewards from consolidated funds
        uint256 timeElapsedConsolidated = block.timestamp.sub(staker.lastRewardUpdateTime);
        uint256 timeFactorConsolidated;
        if(timeElapsedConsolidated >= timeElapsedFactor) {
            timeFactorConsolidated = 1 ether;
        } else {
            timeFactorConsolidated = timeElapsedConsolidated.mul(1 ether).div(timeElapsedFactor);
        }
        uint256 stakerShareFromConsolidated = staker.amountStaked.mul(1 ether).div(totalStakedAmount);
        uint256 rewardFromConsolidated = consolidatedFunds.mul(stakerShareFromConsolidated).div(1 ether);
        rewardFromConsolidated = rewardFromConsolidated.mul(timeFactorConsolidated).div(1 ether);
        if (!ownsActiveNFT(stakerAddress)) {
            rewardFromConsolidated = rewardFromConsolidated.mul(malusNoSubscription).div(100);
        }

        totalReward = totalReward.add(rewardFromConsolidated);
        staker.rewardsEarned = staker.rewardsEarned.add(totalReward);
        staker.lastRewardUpdateTime = block.timestamp;
    }

    function consolidateFunds() private {
        Funds[] memory newFundDeposits = new Funds[](fundDeposits.length);

        uint256 count = 0;
        for (uint256 i = 0; i < fundDeposits.length; i++) {
            uint256 timeElapsed = block.timestamp.sub(fundDeposits[i].depositTime);
            if (timeElapsed >= timeElapsedFactor) {
                consolidatedFunds = consolidatedFunds.add(fundDeposits[i].amount);
            } else {
                newFundDeposits[count] = fundDeposits[i];
                count++;
            }
        }

        if (count > 0) {
            if (fundDeposits.length != count) {
                while (fundDeposits.length > count) {
                    fundDeposits.pop();
                }
                
                for (uint256 i = 0; i < count; i++) {
                    fundDeposits[i] = newFundDeposits[i];
                }
            }
        } else {
            delete fundDeposits;
        }
    }

    function getTotalAvailableRewards() public view returns (uint256) {
        uint256 totalAvailable = consolidatedFunds;

        for (uint256 i = 0; i < fundDeposits.length; i++) {
            totalAvailable = totalAvailable.add(fundDeposits[i].amount);
        }

        return totalAvailable;
    }

    receive() external payable {}

    function depositETH() external payable onlyRewardsProvider {
        fundDeposits.push(Funds({
            amount: msg.value,
            depositTime: block.timestamp
        }));

        if (activateConsolidate){
            consolidateFunds();
        }
    }

    function withdrawFunds() external onlyRewardsProvider {
        uint256 balance = address(this).balance;
        require(balance > 0, "No funds to withdraw");
        payable(msg.sender).transfer(balance);

        delete fundDeposits;
        consolidatedFunds = 0;
    }

    function getStakersArray() public view returns (address[] memory) {
        return stakerAddresses;
    }

    function getFundDepositsArray() public view returns (Funds[] memory) {
        return fundDeposits;
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    function calibrateFundArray(uint256 amount) private {
        uint256 rewardLeftToClaim = amount;
        for (uint256 i = 0; i < fundDeposits.length && rewardLeftToClaim > 0; i++) {
            if (fundDeposits[i].amount == 0) {
                continue;
            }
            if (fundDeposits[i].amount <= rewardLeftToClaim) {
                rewardLeftToClaim = rewardLeftToClaim.sub(fundDeposits[i].amount);
                delete fundDeposits[i];
            } else {
                fundDeposits[i].amount = fundDeposits[i].amount.sub(rewardLeftToClaim);
                rewardLeftToClaim = 0;
            }
        }
        if (rewardLeftToClaim > 0 && consolidatedFunds > 0) {
            if (consolidatedFunds <= rewardLeftToClaim) {
                rewardLeftToClaim = rewardLeftToClaim.sub(consolidatedFunds);
                consolidatedFunds = 0;
            } else {
                consolidatedFunds = consolidatedFunds.sub(rewardLeftToClaim);
                rewardLeftToClaim = 0;
            }
        }
    }

    function ownsActiveNFT(address _user) public view returns (bool) {
        for (uint256 i = 0; i < lockSubNFT.length; i++) {
            if (lockSubNFT[i].instance.getHasValidKey(_user)) {
                return true;
            }
        }
        return false;
    }

    function ownsActiveNFTList(address _user) public view returns (address[] memory) {
        uint256 activeCount = 0;
        for (uint256 i = 0; i < lockSubNFT.length; i++) {
            if (lockSubNFT[i].instance.getHasValidKey(_user)) {
                activeCount++;
            }
        }
        address[] memory activeLockersAddress = new address[](activeCount);

        uint256 j = 0;
        for (uint256 i = 0; i < lockSubNFT.length; i++) {
            if (lockSubNFT[i].instance.getHasValidKey(_user)) {
                activeLockersAddress[j] = address(lockSubNFT[i].nft);
                j++;
            }
        }

        return activeLockersAddress;
    }

    function cleanFundDeposits() external onlyRewardsProvider {
        delete fundDeposits;
    }

    function cleanLockers() external onlyRewardsProvider {
        delete lockSubNFT;
    }

    function setSubscriptionLockers(address[] calldata _lockers) external onlyRewardsProvider {
        for (uint i = 0; i < _lockers.length; i++) {
            address currentLocker = _lockers[i];
            Lockers memory lock;
            lock.instance = IPublicLockV13(currentLocker);
            lock.nft = IERC721(currentLocker);
            lockSubNFT.push(lock);
        }
    }

    function enableContract(bool _c, bool _s) external onlyRewardsProvider {
        enableClaim = _c;
        enableStake = _s;
    }

    function setTotalStakedAmount(uint256 _amount) external onlyRewardsProvider {
        totalStakedAmount = _amount;
    }

    function setRewardsProvider(address _provider) external onlyRewardsProvider {
        rewardsProvider = _provider;
    }

    function setOwner(address _owner) external onlyRewardsProvider {
        owner = _owner;
    }

    function setMaxStakeAmount(uint256 _amount) external onlyRewardsProvider {
        maxStakeAmount = _amount;
    }

    function setMinClaimAmount(uint256 _amount) external onlyRewardsProvider {
        minClaimAmount = _amount;
    }

    function setStakeWaitTime(uint256 _time) external onlyRewardsProvider {
        stakeWaitTime = _time;
    }

    function setClaimInterval(uint256 _interval) external onlyRewardsProvider {
        claimInterval = _interval;
    }

    function setTimeElapsedFactor(uint256 _time) external onlyRewardsProvider {
        timeElapsedFactor = _time;
    }

    function setMalusNoSubscription(uint256 _malus) external onlyRewardsProvider {
        malusNoSubscription = _malus;
    }

    function setRewardResetInterval(uint256 _reset) external onlyRewardsProvider {
        rewardResetInterval = _reset;
    }

    function setTotalDistributed(uint256 _t) external onlyRewardsProvider {
        totalDistributed = _t;
    }

    function setActivateSendTeam(bool _a) external onlyRewardsProvider {
        activateSendTeam = _a;
    }

    function setActivateConsolidate(bool _c) external onlyRewardsProvider {
        activateConsolidate = _c;
    }

    function setActivateRestore(bool _r) external onlyRewardsProvider {
        activateRestore = _r;
    }

    function setConsolidatedFunds(uint256 _c) external onlyRewardsProvider {
        consolidatedFunds = _c;
    }

    function setStaker(address s, uint256 amount, uint256 ls, uint256 lc, uint256 re, uint256 rc, uint256 lr, bool r) external onlyRewardsProvider {
        stakers[s].amountStaked = amount;
        stakers[s].lastStakeTime = ls;
        stakers[s].lastClaimTime = lc;
        stakers[s].rewardsEarned = re;
        stakers[s].rewardsClaimed = rc;
        stakers[s].lastRewardUpdateTime = lr;
        stakers[s].restoring = r;
    }

    function restoreFundDeposit(uint256 amount, uint256 ts) external onlyRewardsProvider {
        fundDeposits.push(Funds({
            amount: amount,
            depositTime: ts
        }));
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_rewardsProvider","type":"address"},{"internalType":"address","name":"_teamWallet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"activateConsolidate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateRestore","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateSendTeam","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"canRestore","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cleanFundDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cleanLockers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"consolidatedFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"enableClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_c","type":"bool"},{"internalType":"bool","name":"_s","type":"bool"}],"name":"enableContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableStake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fundDeposits","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"depositTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFundDepositsArray","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"depositTime","type":"uint256"}],"internalType":"struct RavenFundStakingV2.Funds[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakersArray","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAvailableRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockSubNFT","outputs":[{"internalType":"contract IPublicLockV13","name":"instance","type":"address"},{"internalType":"contract IERC721","name":"nft","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"malusNoSubscription","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxStakeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minClaimAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"ownsActiveNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"ownsActiveNFTList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"previewStakerRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ravenFundStakingOldAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ravenFundStakingV1","outputs":[{"internalType":"contract IRavenFundStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"reasonClaim","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"restoreFundDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restoreStep1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restoreStep2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardResetInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_c","type":"bool"}],"name":"setActivateConsolidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_r","type":"bool"}],"name":"setActivateRestore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_a","type":"bool"}],"name":"setActivateSendTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_interval","type":"uint256"}],"name":"setClaimInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_c","type":"uint256"}],"name":"setConsolidatedFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_malus","type":"uint256"}],"name":"setMalusNoSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMaxStakeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinClaimAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reset","type":"uint256"}],"name":"setRewardResetInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"setRewardsProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"setStakeWaitTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"s","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"ls","type":"uint256"},{"internalType":"uint256","name":"lc","type":"uint256"},{"internalType":"uint256","name":"re","type":"uint256"},{"internalType":"uint256","name":"rc","type":"uint256"},{"internalType":"uint256","name":"lr","type":"uint256"},{"internalType":"bool","name":"r","type":"bool"}],"name":"setStaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_lockers","type":"address[]"}],"name":"setSubscriptionLockers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"setTimeElapsedFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_t","type":"uint256"}],"name":"setTotalDistributed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setTotalStakedAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeWaitTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakerAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint256","name":"amountStaked","type":"uint256"},{"internalType":"uint256","name":"lastStakeTime","type":"uint256"},{"internalType":"uint256","name":"lastClaimTime","type":"uint256"},{"internalType":"uint256","name":"rewardsEarned","type":"uint256"},{"internalType":"uint256","name":"rewardsClaimed","type":"uint256"},{"internalType":"uint256","name":"lastRewardUpdateTime","type":"uint256"},{"internalType":"uint256","name":"keyArray","type":"uint256"},{"internalType":"bool","name":"restoring","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeElapsedFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040526000600881905569032d26d12e980b60000060095561a8c0600a5562015180600b5562093a80600c556213c680600d556046600e55600f8190556010805464ffffffffff19166401010100001790556013553480156200006357600080fd5b5060405162003e4d38038062003e4d833981016040819052620000869162000117565b60016000819055600380546001600160a01b039586166001600160a01b03199182161790915560048054948616948216949094179093556005805492909416918316919091179092556006805482163317905581541673eb94e7cd446a15dcab9c5d04dc5bb805e528dcbb17905562000161565b80516001600160a01b03811681146200011257600080fd5b919050565b6000806000606084860312156200012d57600080fd5b6200013884620000fa565b92506200014860208501620000fa565b91506200015860408501620000fa565b90509250925092565b613cdc80620001716000396000f3fe6080604052600436106103b15760003560e01c80638da5cb5b116101e7578063d52df2e51161010d578063eec78104116100a0578063f60d381f1161006f578063f60d381f14610b34578063f6326fb314610b54578063fe4ce8d414610b5c578063ffebfd9a14610b9157600080fd5b8063eec7810414610ad4578063eef0974014610ae9578063efca2eed14610afe578063f2d57adf14610b1457600080fd5b8063e882779c116100dc578063e882779c14610a54578063e8f2f7f514610a74578063ec3fe6b414610a94578063ecc9747e14610ab457600080fd5b8063d52df2e5146109de578063dcc2a55e146109fe578063e527f48014610a1e578063e61c0f7414610a3457600080fd5b8063adc25bde11610185578063c3c1861611610154578063c3c1861614610971578063c44719a714610986578063c51af512146109a8578063d244448c146109be57600080fd5b8063adc25bde146108f9578063bb7a50f01461090f578063bf3506c11461092f578063bfd108061461094f57600080fd5b8063a1793603116101c1578063a179360314610884578063a434c9d1146108a4578063a48bf0d1146108b9578063a694fc3a146108d957600080fd5b80638da5cb5b146107a65780639168ae72146107c6578063922fc2481461086457600080fd5b80633ea0b6b3116102d75780635d80ca321161026a57806372f702f31161023957806372f702f31461071057806387157c941461073057806389a4b4b6146107505780638bd917fa1461076657600080fd5b80635d80ca321461069a5780635fa505f3146106b05780636319405c146106d05780636ad0530e146106f057600080fd5b80634ba3cef9116102a65780634ba3cef91461063a5780634e71d92d1461064f578063567e98f914610664578063599270441461067a57600080fd5b80633ea0b6b3146105c457806342d1456e146105e4578063459598a2146105fa578063485e670f1461061a57600080fd5b8063127785ab1161034f5780632aea6f5d1161031e5780632aea6f5d146105415780632d767211146105615780632e1a7d4d1461058e5780633bbd1ed2146105ae57600080fd5b8063127785ab146104ba57806313af4035146104f257806324600fc31461051257806328dae6e31461052757600080fd5b80630b433a121161038b5780630b433a12146104335780630d7731ad1461045757806311382e64146104845780631200c165146104a557600080fd5b806302023e67146103bd5780630499de60146103df57806307ffd0f21461041357600080fd5b366103b857005b600080fd5b3480156103c957600080fd5b506103dd6103d83660046136fc565b610bb1565b005b3480156103eb57600080fd5b506010546103fe90610100900460ff1681565b60405190151581526020015b60405180910390f35b34801561041f57600080fd5b506103dd61042e366004613723565b610c13565b34801561043f57600080fd5b50610449600b5481565b60405190815260200161040a565b34801561046357600080fd5b50610477610472366004613763565b610c83565b60405161040a91906137a2565b34801561049057600080fd5b506010546103fe906301000000900460ff1681565b3480156104b157600080fd5b506103dd610e10565b3480156104c657600080fd5b506002546104da906001600160a01b031681565b6040516001600160a01b03909116815260200161040a565b3480156104fe57600080fd5b506103dd61050d366004613763565b61101d565b34801561051e57600080fd5b506103dd611093565b34801561053357600080fd5b506010546103fe9060ff1681565b34801561054d57600080fd5b506004546104da906001600160a01b031681565b34801561056d57600080fd5b5061058161057c366004613763565b61116e565b60405161040a91906137d5565b34801561059a57600080fd5b506103dd6105a93660046136fc565b6113a8565b3480156105ba57600080fd5b5061044960135481565b3480156105d057600080fd5b506010546103fe9062010000900460ff1681565b3480156105f057600080fd5b50610449600a5481565b34801561060657600080fd5b506104da6106153660046136fc565b6115a2565b34801561062657600080fd5b506103dd6106353660046136fc565b6115cc565b34801561064657600080fd5b50610581611625565b34801561065b57600080fd5b506103dd611687565b34801561067057600080fd5b5061044960115481565b34801561068657600080fd5b506005546104da906001600160a01b031681565b3480156106a657600080fd5b5061044960085481565b3480156106bc57600080fd5b506103dd6106cb366004613763565b61191b565b3480156106dc57600080fd5b506103dd6106eb366004613822565b611991565b3480156106fc57600080fd5b506103dd61070b366004613844565b611a5d565b34801561071c57600080fd5b506003546104da906001600160a01b031681565b34801561073c57600080fd5b506103dd61074b3660046138b9565b611b9b565b34801561075c57600080fd5b50610449600c5481565b34801561077257600080fd5b506107866107813660046136fc565b611c3f565b604080516001600160a01b0393841681529290911660208301520161040a565b3480156107b257600080fd5b506006546104da906001600160a01b031681565b3480156107d257600080fd5b506108276107e1366004613763565b6014602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460079097015495969495939492939192909160ff1688565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c0830152151560e08201526101000161040a565b34801561087057600080fd5b506103dd61087f3660046136fc565b611c78565b34801561089057600080fd5b506103dd61089f3660046136fc565b611cd1565b3480156108b057600080fd5b506103dd611d2a565b3480156108c557600080fd5b506103fe6108d4366004613763565b611d8a565b3480156108e557600080fd5b506103dd6108f43660046136fc565b611e50565b34801561090557600080fd5b5061044960095481565b34801561091b57600080fd5b506001546104da906001600160a01b031681565b34801561093b57600080fd5b506103fe61094a366004613763565b612230565b34801561095b57600080fd5b506010546103fe90640100000000900460ff1681565b34801561097d57600080fd5b506103dd6122c4565b34801561099257600080fd5b5061099b6124bf565b60405161040a919061392a565b3480156109b457600080fd5b50610449600e5481565b3480156109ca57600080fd5b506103dd6109d93660046136fc565b612532565b3480156109ea57600080fd5b506103dd6109f9366004613723565b61258b565b348015610a0a57600080fd5b506103dd610a193660046136fc565b6125fd565b348015610a2a57600080fd5b50610449600d5481565b348015610a4057600080fd5b506103dd610a4f366004613723565b612656565b348015610a6057600080fd5b506103dd610a6f3660046136fc565b6126ca565b348015610a8057600080fd5b50610449610a8f366004613763565b612723565b348015610aa057600080fd5b506103dd610aaf3660046136fc565b6129e2565b348015610ac057600080fd5b506103dd610acf3660046136fc565b612a3b565b348015610ae057600080fd5b506103dd612a94565b348015610af557600080fd5b50610449612af4565b348015610b0a57600080fd5b50610449600f5481565b348015610b2057600080fd5b506103dd610b2f3660046136fc565b612b4e565b348015610b4057600080fd5b506103fe610b4f366004613763565b612ba7565b6103dd612c7b565b348015610b6857600080fd5b50610b7c610b773660046136fc565b612d60565b6040805192835260208301919091520161040a565b348015610b9d57600080fd5b506103dd610bac366004613979565b612d8e565b6004546001600160a01b0316331480610bd457506006546001600160a01b031633145b80610be957506005546001600160a01b031633145b610c0e5760405162461bcd60e51b8152600401610c05906139b2565b60405180910390fd5b600f55565b6004546001600160a01b0316331480610c3657506006546001600160a01b031633145b80610c4b57506005546001600160a01b031633145b610c675760405162461bcd60e51b8152600401610c05906139b2565b60108054911515620100000262ff000019909216919091179055565b6001600160a01b0381166000908152601460205260408120606091610ca784612723565b601054909150479060ff16610cd857604051806060016040528060288152602001613c7f6028913995945050505050565b60095483541015610d2a57600954610d0190610cfc90670de0b6b3a7640000612e06565b612e1b565b604051602001610d1191906139e9565b6040516020818303038152906040529350505050919050565b600a548360010154610d3c9190613a63565b4211610d6057610d57600a548460010154610cfc9190613a63565b95945050505050565b600b548360020154610d729190613a63565b4211610d8d57610d57600b548460020154610cfc9190613a63565b60008211610db757604051806060016040528060328152602001613c226032913995945050505050565b81811015610de1576040518060600160405280602b8152602001613c54602b913995945050505050565b505060408051808201909152600f81526e596f752063616e20636c61696d202160881b60208201529392505050565b610e18612eae565b610e2133612ba7565b610e675760405162461bcd60e51b8152602060048201526017602482015276596f752063616e6e6f7420726573746f7265206461746160481b6044820152606401610c05565b601054640100000000900460ff16610ebb5760405162461bcd60e51b8152602060048201526017602482015276596f752063616e6e6f7420726573746f7265206461746160481b6044820152606401610c05565b6001546040516348b4573960e11b81523360048201526000918291829182918291829182916001600160a01b031690639168ae729060240160e060405180830381865afa158015610f10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f349190613a76565b60408051610100810182529788526020808901978852888201968752606089019586526080890194855260a0890193845260c08901928352600160e08a0181815233600081815260149094529390922099518a55975189890155955160028901559351600388015591516004870155516005860155516006850190815591516007909401805460ff1916941515949094179093556015805492830181557f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47590920180546001600160a01b0319169093179092555490555061101b9550612f07945050505050565b565b6004546001600160a01b031633148061104057506006546001600160a01b031633145b8061105557506005546001600160a01b031633145b6110715760405162461bcd60e51b8152600401610c05906139b2565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314806110b657506006546001600160a01b031633145b806110cb57506005546001600160a01b031633145b6110e75760405162461bcd60e51b8152600401610c05906139b2565b478061112c5760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610c05565b604051339082156108fc029083906000818181858888f19350505050158015611159573d6000803e3d6000fd5b506111666012600061366f565b506000601355565b60606000805b600754811015611232576007818154811061119157611191613aca565b6000918252602090912060029091020154604051631b63a96d60e21b81526001600160a01b03868116600483015290911690636d8ea5b490602401602060405180830381865afa1580156111e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120d9190613ae0565b15611220578161121c81613afd565b9250505b8061122a81613afd565b915050611174565b5060008167ffffffffffffffff81111561124e5761124e613b16565b604051908082528060200260200182016040528015611277578160200160208202803683370190505b5090506000805b60075481101561139e576007818154811061129b5761129b613aca565b6000918252602090912060029091020154604051631b63a96d60e21b81526001600160a01b03888116600483015290911690636d8ea5b490602401602060405180830381865afa1580156112f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113179190613ae0565b1561138c576007818154811061132f5761132f613aca565b906000526020600020906002020160010160009054906101000a90046001600160a01b031683838151811061136657611366613aca565b6001600160a01b03909216602092830291909101909101528161138881613afd565b9250505b8061139681613afd565b91505061127e565b5090949350505050565b6113b0612eae565b3360009081526014602052604090208161140c5760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610c05565b805482111561145d5760405162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e74207374616b656420616d6f756e740000000000006044820152606401610c05565b80546114699083612f0e565b81556011546114789083612f0e565b60115580546115035760038101805460009091554260028301554781158015906114a25750818110155b80156114b6575060105462010000900460ff165b15611500576114c482612f1a565b6005546040516001600160a01b039091169083156108fc029084906000818181858888f193505050501580156114fe573d6000803e3d6000fd5b505b50505b60035460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303816000875af1158015611554573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115789190613ae0565b6115945760405162461bcd60e51b8152600401610c0590613b2c565b5061159f6001600055565b50565b601581815481106115b257600080fd5b6000918252602090912001546001600160a01b0316905081565b6004546001600160a01b03163314806115ef57506006546001600160a01b031633145b8061160457506005546001600160a01b031633145b6116205760405162461bcd60e51b8152600401610c05906139b2565b600c55565b6060601580548060200260200160405190810160405280929190818152602001828054801561167d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161165f575b5050505050905090565b61168f612eae565b60105460ff166116d65760405162461bcd60e51b815260206004820152601260248201527121b630b4b6903737ba1032b730b13632b21760711b6044820152606401610c05565b336000908152601460205260409020600954815410156117435760405162461bcd60e51b815260206004820152602260248201527f4e6f7420656e6f75676820746f6b656e73207374616b656420746f20636c6169604482015261369760f11b6064820152608401610c05565b600a5481600101546117559190613a63565b42116117a35760405162461bcd60e51b815260206004820152601a60248201527f4e65656420746f2077616974206166746572207374616b696e670000000000006044820152606401610c05565b600b5481600201546117b59190613a63565b42116118035760405162461bcd60e51b815260206004820152601860248201527f416c726561647920636c61696d656420726563656e746c7900000000000000006044820152606401610c05565b61180c336130a0565b6003810154806118555760405162461bcd60e51b81526020600482015260146024820152734e6f207265776172647320617661696c61626c6560601b6044820152606401610c05565b47818110156118a65760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682045544820696e2074686520636f6e747261637400006044820152606401610c05565b6118af82612f1a565b6000600384015542600284015560048301546118cb9083613336565b6004840155600f546118dd9083613336565b600f55604051339083156108fc029084906000818181858888f1935050505015801561190d573d6000803e3d6000fd5b5050505061101b6001600055565b6004546001600160a01b031633148061193e57506006546001600160a01b031633145b8061195357506005546001600160a01b031633145b61196f5760405162461bcd60e51b8152600401610c05906139b2565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314806119b457506006546001600160a01b031633145b806119c957506005546001600160a01b031633145b6119e55760405162461bcd60e51b8152600401610c05906139b2565b60408051808201909152918252602082019081526012805460018101825560009190915291517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600290930292830155517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344590910155565b6004546001600160a01b0316331480611a8057506006546001600160a01b031633145b80611a9557506005546001600160a01b031633145b611ab15760405162461bcd60e51b8152600401610c05906139b2565b60005b81811015611b96576000838383818110611ad057611ad0613aca565b9050602002016020810190611ae59190613763565b604080518082019091526001600160a01b039182168082526020820190815260078054600181018255600091909152915160029092027fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688810180549385166001600160a01b031994851617905590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68990910180549190931691161790555080611b8e81613afd565b915050611ab4565b505050565b6004546001600160a01b0316331480611bbe57506006546001600160a01b031633145b80611bd357506005546001600160a01b031633145b611bef5760405162461bcd60e51b8152600401610c05906139b2565b6001600160a01b0397909716600090815260146020526040902095865560018601949094556002850192909255600384015560048301556005820155600701805460ff1916911515919091179055565b60078181548110611c4f57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692501682565b6004546001600160a01b0316331480611c9b57506006546001600160a01b031633145b80611cb057506005546001600160a01b031633145b611ccc5760405162461bcd60e51b8152600401610c05906139b2565b600955565b6004546001600160a01b0316331480611cf457506006546001600160a01b031633145b80611d0957506005546001600160a01b031633145b611d255760405162461bcd60e51b8152600401610c05906139b2565b600d55565b6004546001600160a01b0316331480611d4d57506006546001600160a01b031633145b80611d6257506005546001600160a01b031633145b611d7e5760405162461bcd60e51b8152600401610c05906139b2565b61101b6012600061366f565b6000805b600754811015611e475760078181548110611dab57611dab613aca565b6000918252602090912060029091020154604051631b63a96d60e21b81526001600160a01b03858116600483015290911690636d8ea5b490602401602060405180830381865afa158015611e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e279190613ae0565b15611e355750600192915050565b80611e3f81613afd565b915050611d8e565b50600092915050565b611e58612eae565b601054610100900460ff16611ea45760405162461bcd60e51b815260206004820152601260248201527129ba30b5b2903737ba1032b730b13632b21760711b6044820152606401610c05565b6001546040516348b4573960e11b81523360048201526000918291829182918291829182916001600160a01b031690639168ae729060240160e060405180830381865afa158015611ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1d9190613a76565b96509650965096509650965096506000871115611f925760405162461bcd60e51b815260206004820152602d60248201527f526573746f726520796f757220746f6b656e20746f20746865206e657720636f60448201526c6e7472616374206265666f726560981b6064820152608401610c05565b336000908152601460205260409020600781015460ff16156120005760405162461bcd60e51b815260206004820152602160248201527f46696e69736820726573746f7265206265666f7265207374616b6520616761696044820152603760f91b6064820152608401610c05565b60085415612066576008548154612018908b90613a63565b11156120665760405162461bcd60e51b815260206004820152601860248201527f4d6178207374616b6520616d6f756e74207265616368656400000000000000006044820152606401610c05565b8060050154600003612079574260058201555b80600601546000036120cd576015805460018101825560008290527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec4750180546001600160a01b031916331790555460068201555b600354604051636eb1769f60e11b81523360048201523060248201526000916001600160a01b03169063dd62ed3e90604401602060405180830381865afa15801561211c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121409190613b5b565b9050898110156121625760405162461bcd60e51b8152600401610c0590613b74565b4260018301558154612174908b613336565b8255601154612183908b613336565b6011556003546040516323b872dd60e01b8152336004820152306024820152604481018c90526001600160a01b03909116906323b872dd906064016020604051808303816000875af11580156121dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122019190613ae0565b61221d5760405162461bcd60e51b8152600401610c0590613b2c565b50505050505050505061159f6001600055565b6001600160a01b03811660009081526014602052604081208161225284612723565b601054909150479060ff1680156122695750600082115b80156122755750818110155b80156122845750600954835410155b80156122a05750600a54836001015461229d9190613a63565b42115b8015610d575750600b5483600201546122b99190613a63565b421195945050505050565b6122cc612eae565b336000908152601460205260409020805461231e5760405162461bcd60e51b81526020600482015260126024820152714e6f7468696e6720746f20726573746f726560701b6044820152606401610c05565b600781015460ff166123685760405162461bcd60e51b81526020600482015260136024820152724e6f7420696e20726573746f7265206d6f646560681b6044820152606401610c05565b600354604051636eb1769f60e11b81523360048201523060248201526000916001600160a01b03169063dd62ed3e90604401602060405180830381865afa1580156123b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123db9190613b5b565b82549091508110156123ff5760405162461bcd60e51b8152600401610c0590613b74565b60035482546040516323b872dd60e01b815233600482015230602482015260448101919091526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d9190613ae0565b6124995760405162461bcd60e51b8152600401610c0590613b2c565b60078201805460ff1916905581546011546124b391613336565b60115550506001600055565b60606012805480602002602001604051908101604052809291908181526020016000905b82821015612529578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906124e3565b50505050905090565b6004546001600160a01b031633148061255557506006546001600160a01b031633145b8061256a57506005546001600160a01b031633145b6125865760405162461bcd60e51b8152600401610c05906139b2565b600e55565b6004546001600160a01b03163314806125ae57506006546001600160a01b031633145b806125c357506005546001600160a01b031633145b6125df5760405162461bcd60e51b8152600401610c05906139b2565b6010805491151563010000000263ff00000019909216919091179055565b6004546001600160a01b031633148061262057506006546001600160a01b031633145b8061263557506005546001600160a01b031633145b6126515760405162461bcd60e51b8152600401610c05906139b2565b600855565b6004546001600160a01b031633148061267957506006546001600160a01b031633145b8061268e57506005546001600160a01b031633145b6126aa5760405162461bcd60e51b8152600401610c05906139b2565b601080549115156401000000000264ff0000000019909216919091179055565b6004546001600160a01b03163314806126ed57506006546001600160a01b031633145b8061270257506005546001600160a01b031633145b61271e5760405162461bcd60e51b8152600401610c05906139b2565b601355565b6001600160a01b03811660009081526014602052604081206009548154108061274c5750601154155b806127575750600c54155b15612766576003015492915050565b6000805b6012548110156128e1576012818154811061278757612787613aca565b6000918252602090912060029091020154156128cf5760006127d18460050154601284815481106127ba576127ba613aca565b906000526020600020906002020160010154613342565b905060006127df4283612f0e565b90506000600c5482106127fb5750670de0b6b3a764000061281d565b600c5461281a9061281484670de0b6b3a7640000613358565b90612e06565b90505b601154865460009161283b9161281490670de0b6b3a7640000613358565b90506000612879670de0b6b3a76400006128148460128a8154811061286257612862613aca565b600091825260209091206002909102015490613358565b9050612891670de0b6b3a76400006128148386613358565b905061289c8a611d8a565b6128bd576128ba6064612814600e548461335890919063ffffffff16565b90505b6128c78782613336565b965050505050505b806128d981613afd565b91505061276a565b5060006128fb836005015442612f0e90919063ffffffff16565b90506000600c5482106129175750670de0b6b3a7640000612933565b600c546129309061281484670de0b6b3a7640000613358565b90505b60115484546000916129519161281490670de0b6b3a7640000613358565b90506000612976670de0b6b3a76400006128148460135461335890919063ffffffff16565b905061298e670de0b6b3a76400006128148386613358565b905061299988611d8a565b6129ba576129b76064612814600e548461335890919063ffffffff16565b90505b6129c48582613336565b60038701549095506129d69086613336565b98975050505050505050565b6004546001600160a01b0316331480612a0557506006546001600160a01b031633145b80612a1a57506005546001600160a01b031633145b612a365760405162461bcd60e51b8152600401610c05906139b2565b600a55565b6004546001600160a01b0316331480612a5e57506006546001600160a01b031633145b80612a7357506005546001600160a01b031633145b612a8f5760405162461bcd60e51b8152600401610c05906139b2565b601155565b6004546001600160a01b0316331480612ab757506006546001600160a01b031633145b80612acc57506005546001600160a01b031633145b612ae85760405162461bcd60e51b8152600401610c05906139b2565b61101b60076000613690565b601354600090815b601254811015612b4857612b3460128281548110612b1c57612b1c613aca565b60009182526020909120600290910201548390613336565b915080612b4081613afd565b915050612afc565b50919050565b6004546001600160a01b0316331480612b7157506006546001600160a01b031633145b80612b8657506005546001600160a01b031633145b612ba25760405162461bcd60e51b8152600401610c05906139b2565b600b55565b6001546040516348b4573960e11b81526001600160a01b0383811660048301526000928392839283928392839283928392911690639168ae729060240160e060405180830381865afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c259190613a76565b96509650965096509650965096506000871115612c6c576001600160a01b03891660009081526014602052604090208054612c6a575060019998505050505050505050565b505b50600098975050505050505050565b6004546001600160a01b0316331480612c9e57506006546001600160a01b031633145b80612cb357506005546001600160a01b031633145b612ccf5760405162461bcd60e51b8152600401610c05906139b2565b6040805180820190915234815242602082019081526012805460018101825560009190915291517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600290930292830155517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3445909101556010546301000000900460ff161561101b5761101b613364565b60128181548110612d7057600080fd5b60009182526020909120600290910201805460019091015490915082565b6004546001600160a01b0316331480612db157506006546001600160a01b031633145b80612dc657506005546001600160a01b031633145b612de25760405162461bcd60e51b8152600401610c05906139b2565b6010805461ffff191692151561ff0019169290921761010091151591909102179055565b6000612e128284613bbf565b90505b92915050565b60606000612e2883613597565b600101905060008167ffffffffffffffff811115612e4857612e48613b16565b6040519080825280601f01601f191660200182016040528015612e72576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612e7c57509392505050565b600260005403612f005760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c05565b6002600055565b6001600055565b6000612e128284613be1565b8060005b60125481108015612f2f5750600082115b1561304f5760128181548110612f4757612f47613aca565b60009182526020909120600290910201541561303d578160128281548110612f7157612f71613aca565b90600052602060002090600202016000015411612fe657612fb660128281548110612f9e57612f9e613aca565b60009182526020909120600290910201548390612f0e565b915060128181548110612fcb57612fcb613aca565b6000918252602082206002909102018181556001015561303d565b6130148260128381548110612ffd57612ffd613aca565b600091825260209091206002909102015490612f0e565b6012828154811061302757613027613aca565b6000918252602082206002909102019190915591505b8061304781613afd565b915050612f1e565b5060008111801561306257506000601354115b1561309c5780601354116130885760135461307e908290612f0e565b5050600060135550565b6013546130959082612f0e565b6013555060005b5050565b6001600160a01b0381166000908152601460205260409020600954815410806130c95750601154155b806130d45750600c54155b156130e3574260059091015550565b6000805b60125481101561322a576012818154811061310457613104613aca565b6000918252602090912060029091020154156132185760006131378460050154601284815481106127ba576127ba613aca565b905060006131454283612f0e565b90506000600c5482106131615750670de0b6b3a764000061317d565b600c5461317a9061281484670de0b6b3a7640000613358565b90505b601154865460009161319b9161281490670de0b6b3a7640000613358565b905060006131c2670de0b6b3a76400006128148460128a8154811061286257612862613aca565b90506131da670de0b6b3a76400006128148386613358565b90506131e589611d8a565b613206576132036064612814600e548461335890919063ffffffff16565b90505b6132108782613336565b965050505050505b8061322281613afd565b9150506130e7565b506000613244836005015442612f0e90919063ffffffff16565b90506000600c5482106132605750670de0b6b3a764000061327c565b600c546132799061281484670de0b6b3a7640000613358565b90505b601154845460009161329a9161281490670de0b6b3a7640000613358565b905060006132bf670de0b6b3a76400006128148460135461335890919063ffffffff16565b90506132d7670de0b6b3a76400006128148386613358565b90506132e287611d8a565b613303576133006064612814600e548461335890919063ffffffff16565b90505b61330d8582613336565b600387015490955061331f9086613336565b600387015550504260059094019390935550505050565b6000612e128284613a63565b60008183116133515781612e12565b5090919050565b6000612e128284613bf4565b60125460009067ffffffffffffffff81111561338257613382613b16565b6040519080825280602002602001820160405280156133c757816020015b60408051808201909152600080825260208201528152602001906001900390816133a05790505b5090506000805b6012548110156134d3576000613411601283815481106133f0576133f0613aca565b90600052602060002090600202016001015442612f0e90919063ffffffff16565b9050600c5481106134545761344c6012838154811061343257613432613aca565b600091825260209091206002909102015460135490613336565b6013556134c0565b6012828154811061346757613467613aca565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508484815181106134a6576134a6613aca565b602002602001018190525082806134bc90613afd565b9350505b50806134cb81613afd565b9150506133ce565b50801561358b57601254811461309c575b6012548110156135225760128054806134ff576134ff613c0b565b6000828152602081206002600019909301928302018181556001015590556134e4565b60005b81811015611b965782818151811061353f5761353f613aca565b60200260200101516012828154811061355a5761355a613aca565b600091825260209182902083516002909202019081559101516001909101558061358381613afd565b915050613525565b61309c6012600061366f565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106135d65772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310613602576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061362057662386f26fc10000830492506010015b6305f5e1008310613638576305f5e100830492506008015b612710831061364c57612710830492506004015b6064831061365e576064830492506002015b600a8310612e155760010192915050565b508054600082556002029060005260206000209081019061159f91906136b1565b508054600082556002029060005260206000209081019061159f91906136d0565b5b808211156136cc57600080825560018201556002016136b2565b5090565b5b808211156136cc5780546001600160a01b0319908116825560018201805490911690556002016136d1565b60006020828403121561370e57600080fd5b5035919050565b801515811461159f57600080fd5b60006020828403121561373557600080fd5b813561374081613715565b9392505050565b80356001600160a01b038116811461375e57600080fd5b919050565b60006020828403121561377557600080fd5b612e1282613747565b60005b83811015613799578181015183820152602001613781565b50506000910152565b60208152600082518060208401526137c181604085016020870161377e565b601f01601f19169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b818110156138165783516001600160a01b0316835292840192918401916001016137f1565b50909695505050505050565b6000806040838503121561383557600080fd5b50508035926020909101359150565b6000806020838503121561385757600080fd5b823567ffffffffffffffff8082111561386f57600080fd5b818501915085601f83011261388357600080fd5b81358181111561389257600080fd5b8660208260051b85010111156138a757600080fd5b60209290920196919550909350505050565b600080600080600080600080610100898b0312156138d657600080fd5b6138df89613747565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c0890135915060e089013561391981613715565b809150509295985092959890939650565b602080825282518282018190526000919060409081850190868401855b8281101561396c57815180518552860151868501529284019290850190600101613947565b5091979650505050505050565b6000806040838503121561398c57600080fd5b823561399781613715565b915060208301356139a781613715565b809150509250929050565b60208082526018908201527f4e6f742074686520726577617264732070726f76696465720000000000000000604082015260600190565b7f546f20626520656c696769626c652c20796f75206861766520746f207374616b81527503290309036b4b734b6bab690122920ab22a71037b3160551b602082015260008251613a4081603685016020870161377e565b9190910160360192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115612e1557612e15613a4d565b600080600080600080600060e0888a031215613a9157600080fd5b5050855160208701516040880151606089015160808a015160a08b015160c0909b0151949c939b50919990985090965094509092509050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613af257600080fd5b815161374081613715565b600060018201613b0f57613b0f613a4d565b5060010190565b634e487b7160e01b600052604160045260246000fd5b602080825260159082015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b600060208284031215613b6d57600080fd5b5051919050565b6020808252602b908201527f416c6c6f77616e6365206973206e6f742073756666696369656e7420746f207360408201526a74616b6520746f6b656e7360a81b606082015260800190565b600082613bdc57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115612e1557612e15613a4d565b8082028115828204841417612e1557612e15613a4d565b634e487b7160e01b600052603160045260246000fdfe596f7520646f6e2774206861766520616e792072657761726420746f20636c61696d20666f7220746865206d6f6d656e742e506c656173652077616974206e65772066756e647320746f20636c61696d20796f7572207265776172642e436c61696d206e6f7420656e61626c65642c20706c6561736520776169742061206d6f6d656e742ea26469706673582212203b4e95dac3593199a80bae625b926683b8143a6b69f79c4696cc7f12042b573664736f6c6343000813003300000000000000000000000043af0944b34ad466dcea7fc8f77aafc6a4ec70fa000000000000000000000000d7cd7131a6e558bc71ec4e3ae39074d6cb0882c60000000000000000000000008892c1843e632b9649e0cc8ad09e26c0198f7e30

Deployed Bytecode

0x6080604052600436106103b15760003560e01c80638da5cb5b116101e7578063d52df2e51161010d578063eec78104116100a0578063f60d381f1161006f578063f60d381f14610b34578063f6326fb314610b54578063fe4ce8d414610b5c578063ffebfd9a14610b9157600080fd5b8063eec7810414610ad4578063eef0974014610ae9578063efca2eed14610afe578063f2d57adf14610b1457600080fd5b8063e882779c116100dc578063e882779c14610a54578063e8f2f7f514610a74578063ec3fe6b414610a94578063ecc9747e14610ab457600080fd5b8063d52df2e5146109de578063dcc2a55e146109fe578063e527f48014610a1e578063e61c0f7414610a3457600080fd5b8063adc25bde11610185578063c3c1861611610154578063c3c1861614610971578063c44719a714610986578063c51af512146109a8578063d244448c146109be57600080fd5b8063adc25bde146108f9578063bb7a50f01461090f578063bf3506c11461092f578063bfd108061461094f57600080fd5b8063a1793603116101c1578063a179360314610884578063a434c9d1146108a4578063a48bf0d1146108b9578063a694fc3a146108d957600080fd5b80638da5cb5b146107a65780639168ae72146107c6578063922fc2481461086457600080fd5b80633ea0b6b3116102d75780635d80ca321161026a57806372f702f31161023957806372f702f31461071057806387157c941461073057806389a4b4b6146107505780638bd917fa1461076657600080fd5b80635d80ca321461069a5780635fa505f3146106b05780636319405c146106d05780636ad0530e146106f057600080fd5b80634ba3cef9116102a65780634ba3cef91461063a5780634e71d92d1461064f578063567e98f914610664578063599270441461067a57600080fd5b80633ea0b6b3146105c457806342d1456e146105e4578063459598a2146105fa578063485e670f1461061a57600080fd5b8063127785ab1161034f5780632aea6f5d1161031e5780632aea6f5d146105415780632d767211146105615780632e1a7d4d1461058e5780633bbd1ed2146105ae57600080fd5b8063127785ab146104ba57806313af4035146104f257806324600fc31461051257806328dae6e31461052757600080fd5b80630b433a121161038b5780630b433a12146104335780630d7731ad1461045757806311382e64146104845780631200c165146104a557600080fd5b806302023e67146103bd5780630499de60146103df57806307ffd0f21461041357600080fd5b366103b857005b600080fd5b3480156103c957600080fd5b506103dd6103d83660046136fc565b610bb1565b005b3480156103eb57600080fd5b506010546103fe90610100900460ff1681565b60405190151581526020015b60405180910390f35b34801561041f57600080fd5b506103dd61042e366004613723565b610c13565b34801561043f57600080fd5b50610449600b5481565b60405190815260200161040a565b34801561046357600080fd5b50610477610472366004613763565b610c83565b60405161040a91906137a2565b34801561049057600080fd5b506010546103fe906301000000900460ff1681565b3480156104b157600080fd5b506103dd610e10565b3480156104c657600080fd5b506002546104da906001600160a01b031681565b6040516001600160a01b03909116815260200161040a565b3480156104fe57600080fd5b506103dd61050d366004613763565b61101d565b34801561051e57600080fd5b506103dd611093565b34801561053357600080fd5b506010546103fe9060ff1681565b34801561054d57600080fd5b506004546104da906001600160a01b031681565b34801561056d57600080fd5b5061058161057c366004613763565b61116e565b60405161040a91906137d5565b34801561059a57600080fd5b506103dd6105a93660046136fc565b6113a8565b3480156105ba57600080fd5b5061044960135481565b3480156105d057600080fd5b506010546103fe9062010000900460ff1681565b3480156105f057600080fd5b50610449600a5481565b34801561060657600080fd5b506104da6106153660046136fc565b6115a2565b34801561062657600080fd5b506103dd6106353660046136fc565b6115cc565b34801561064657600080fd5b50610581611625565b34801561065b57600080fd5b506103dd611687565b34801561067057600080fd5b5061044960115481565b34801561068657600080fd5b506005546104da906001600160a01b031681565b3480156106a657600080fd5b5061044960085481565b3480156106bc57600080fd5b506103dd6106cb366004613763565b61191b565b3480156106dc57600080fd5b506103dd6106eb366004613822565b611991565b3480156106fc57600080fd5b506103dd61070b366004613844565b611a5d565b34801561071c57600080fd5b506003546104da906001600160a01b031681565b34801561073c57600080fd5b506103dd61074b3660046138b9565b611b9b565b34801561075c57600080fd5b50610449600c5481565b34801561077257600080fd5b506107866107813660046136fc565b611c3f565b604080516001600160a01b0393841681529290911660208301520161040a565b3480156107b257600080fd5b506006546104da906001600160a01b031681565b3480156107d257600080fd5b506108276107e1366004613763565b6014602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460079097015495969495939492939192909160ff1688565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c0830152151560e08201526101000161040a565b34801561087057600080fd5b506103dd61087f3660046136fc565b611c78565b34801561089057600080fd5b506103dd61089f3660046136fc565b611cd1565b3480156108b057600080fd5b506103dd611d2a565b3480156108c557600080fd5b506103fe6108d4366004613763565b611d8a565b3480156108e557600080fd5b506103dd6108f43660046136fc565b611e50565b34801561090557600080fd5b5061044960095481565b34801561091b57600080fd5b506001546104da906001600160a01b031681565b34801561093b57600080fd5b506103fe61094a366004613763565b612230565b34801561095b57600080fd5b506010546103fe90640100000000900460ff1681565b34801561097d57600080fd5b506103dd6122c4565b34801561099257600080fd5b5061099b6124bf565b60405161040a919061392a565b3480156109b457600080fd5b50610449600e5481565b3480156109ca57600080fd5b506103dd6109d93660046136fc565b612532565b3480156109ea57600080fd5b506103dd6109f9366004613723565b61258b565b348015610a0a57600080fd5b506103dd610a193660046136fc565b6125fd565b348015610a2a57600080fd5b50610449600d5481565b348015610a4057600080fd5b506103dd610a4f366004613723565b612656565b348015610a6057600080fd5b506103dd610a6f3660046136fc565b6126ca565b348015610a8057600080fd5b50610449610a8f366004613763565b612723565b348015610aa057600080fd5b506103dd610aaf3660046136fc565b6129e2565b348015610ac057600080fd5b506103dd610acf3660046136fc565b612a3b565b348015610ae057600080fd5b506103dd612a94565b348015610af557600080fd5b50610449612af4565b348015610b0a57600080fd5b50610449600f5481565b348015610b2057600080fd5b506103dd610b2f3660046136fc565b612b4e565b348015610b4057600080fd5b506103fe610b4f366004613763565b612ba7565b6103dd612c7b565b348015610b6857600080fd5b50610b7c610b773660046136fc565b612d60565b6040805192835260208301919091520161040a565b348015610b9d57600080fd5b506103dd610bac366004613979565b612d8e565b6004546001600160a01b0316331480610bd457506006546001600160a01b031633145b80610be957506005546001600160a01b031633145b610c0e5760405162461bcd60e51b8152600401610c05906139b2565b60405180910390fd5b600f55565b6004546001600160a01b0316331480610c3657506006546001600160a01b031633145b80610c4b57506005546001600160a01b031633145b610c675760405162461bcd60e51b8152600401610c05906139b2565b60108054911515620100000262ff000019909216919091179055565b6001600160a01b0381166000908152601460205260408120606091610ca784612723565b601054909150479060ff16610cd857604051806060016040528060288152602001613c7f6028913995945050505050565b60095483541015610d2a57600954610d0190610cfc90670de0b6b3a7640000612e06565b612e1b565b604051602001610d1191906139e9565b6040516020818303038152906040529350505050919050565b600a548360010154610d3c9190613a63565b4211610d6057610d57600a548460010154610cfc9190613a63565b95945050505050565b600b548360020154610d729190613a63565b4211610d8d57610d57600b548460020154610cfc9190613a63565b60008211610db757604051806060016040528060328152602001613c226032913995945050505050565b81811015610de1576040518060600160405280602b8152602001613c54602b913995945050505050565b505060408051808201909152600f81526e596f752063616e20636c61696d202160881b60208201529392505050565b610e18612eae565b610e2133612ba7565b610e675760405162461bcd60e51b8152602060048201526017602482015276596f752063616e6e6f7420726573746f7265206461746160481b6044820152606401610c05565b601054640100000000900460ff16610ebb5760405162461bcd60e51b8152602060048201526017602482015276596f752063616e6e6f7420726573746f7265206461746160481b6044820152606401610c05565b6001546040516348b4573960e11b81523360048201526000918291829182918291829182916001600160a01b031690639168ae729060240160e060405180830381865afa158015610f10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f349190613a76565b60408051610100810182529788526020808901978852888201968752606089019586526080890194855260a0890193845260c08901928352600160e08a0181815233600081815260149094529390922099518a55975189890155955160028901559351600388015591516004870155516005860155516006850190815591516007909401805460ff1916941515949094179093556015805492830181557f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47590920180546001600160a01b0319169093179092555490555061101b9550612f07945050505050565b565b6004546001600160a01b031633148061104057506006546001600160a01b031633145b8061105557506005546001600160a01b031633145b6110715760405162461bcd60e51b8152600401610c05906139b2565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314806110b657506006546001600160a01b031633145b806110cb57506005546001600160a01b031633145b6110e75760405162461bcd60e51b8152600401610c05906139b2565b478061112c5760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610c05565b604051339082156108fc029083906000818181858888f19350505050158015611159573d6000803e3d6000fd5b506111666012600061366f565b506000601355565b60606000805b600754811015611232576007818154811061119157611191613aca565b6000918252602090912060029091020154604051631b63a96d60e21b81526001600160a01b03868116600483015290911690636d8ea5b490602401602060405180830381865afa1580156111e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120d9190613ae0565b15611220578161121c81613afd565b9250505b8061122a81613afd565b915050611174565b5060008167ffffffffffffffff81111561124e5761124e613b16565b604051908082528060200260200182016040528015611277578160200160208202803683370190505b5090506000805b60075481101561139e576007818154811061129b5761129b613aca565b6000918252602090912060029091020154604051631b63a96d60e21b81526001600160a01b03888116600483015290911690636d8ea5b490602401602060405180830381865afa1580156112f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113179190613ae0565b1561138c576007818154811061132f5761132f613aca565b906000526020600020906002020160010160009054906101000a90046001600160a01b031683838151811061136657611366613aca565b6001600160a01b03909216602092830291909101909101528161138881613afd565b9250505b8061139681613afd565b91505061127e565b5090949350505050565b6113b0612eae565b3360009081526014602052604090208161140c5760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610c05565b805482111561145d5760405162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e74207374616b656420616d6f756e740000000000006044820152606401610c05565b80546114699083612f0e565b81556011546114789083612f0e565b60115580546115035760038101805460009091554260028301554781158015906114a25750818110155b80156114b6575060105462010000900460ff165b15611500576114c482612f1a565b6005546040516001600160a01b039091169083156108fc029084906000818181858888f193505050501580156114fe573d6000803e3d6000fd5b505b50505b60035460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303816000875af1158015611554573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115789190613ae0565b6115945760405162461bcd60e51b8152600401610c0590613b2c565b5061159f6001600055565b50565b601581815481106115b257600080fd5b6000918252602090912001546001600160a01b0316905081565b6004546001600160a01b03163314806115ef57506006546001600160a01b031633145b8061160457506005546001600160a01b031633145b6116205760405162461bcd60e51b8152600401610c05906139b2565b600c55565b6060601580548060200260200160405190810160405280929190818152602001828054801561167d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161165f575b5050505050905090565b61168f612eae565b60105460ff166116d65760405162461bcd60e51b815260206004820152601260248201527121b630b4b6903737ba1032b730b13632b21760711b6044820152606401610c05565b336000908152601460205260409020600954815410156117435760405162461bcd60e51b815260206004820152602260248201527f4e6f7420656e6f75676820746f6b656e73207374616b656420746f20636c6169604482015261369760f11b6064820152608401610c05565b600a5481600101546117559190613a63565b42116117a35760405162461bcd60e51b815260206004820152601a60248201527f4e65656420746f2077616974206166746572207374616b696e670000000000006044820152606401610c05565b600b5481600201546117b59190613a63565b42116118035760405162461bcd60e51b815260206004820152601860248201527f416c726561647920636c61696d656420726563656e746c7900000000000000006044820152606401610c05565b61180c336130a0565b6003810154806118555760405162461bcd60e51b81526020600482015260146024820152734e6f207265776172647320617661696c61626c6560601b6044820152606401610c05565b47818110156118a65760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682045544820696e2074686520636f6e747261637400006044820152606401610c05565b6118af82612f1a565b6000600384015542600284015560048301546118cb9083613336565b6004840155600f546118dd9083613336565b600f55604051339083156108fc029084906000818181858888f1935050505015801561190d573d6000803e3d6000fd5b5050505061101b6001600055565b6004546001600160a01b031633148061193e57506006546001600160a01b031633145b8061195357506005546001600160a01b031633145b61196f5760405162461bcd60e51b8152600401610c05906139b2565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314806119b457506006546001600160a01b031633145b806119c957506005546001600160a01b031633145b6119e55760405162461bcd60e51b8152600401610c05906139b2565b60408051808201909152918252602082019081526012805460018101825560009190915291517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600290930292830155517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344590910155565b6004546001600160a01b0316331480611a8057506006546001600160a01b031633145b80611a9557506005546001600160a01b031633145b611ab15760405162461bcd60e51b8152600401610c05906139b2565b60005b81811015611b96576000838383818110611ad057611ad0613aca565b9050602002016020810190611ae59190613763565b604080518082019091526001600160a01b039182168082526020820190815260078054600181018255600091909152915160029092027fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688810180549385166001600160a01b031994851617905590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68990910180549190931691161790555080611b8e81613afd565b915050611ab4565b505050565b6004546001600160a01b0316331480611bbe57506006546001600160a01b031633145b80611bd357506005546001600160a01b031633145b611bef5760405162461bcd60e51b8152600401610c05906139b2565b6001600160a01b0397909716600090815260146020526040902095865560018601949094556002850192909255600384015560048301556005820155600701805460ff1916911515919091179055565b60078181548110611c4f57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692501682565b6004546001600160a01b0316331480611c9b57506006546001600160a01b031633145b80611cb057506005546001600160a01b031633145b611ccc5760405162461bcd60e51b8152600401610c05906139b2565b600955565b6004546001600160a01b0316331480611cf457506006546001600160a01b031633145b80611d0957506005546001600160a01b031633145b611d255760405162461bcd60e51b8152600401610c05906139b2565b600d55565b6004546001600160a01b0316331480611d4d57506006546001600160a01b031633145b80611d6257506005546001600160a01b031633145b611d7e5760405162461bcd60e51b8152600401610c05906139b2565b61101b6012600061366f565b6000805b600754811015611e475760078181548110611dab57611dab613aca565b6000918252602090912060029091020154604051631b63a96d60e21b81526001600160a01b03858116600483015290911690636d8ea5b490602401602060405180830381865afa158015611e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e279190613ae0565b15611e355750600192915050565b80611e3f81613afd565b915050611d8e565b50600092915050565b611e58612eae565b601054610100900460ff16611ea45760405162461bcd60e51b815260206004820152601260248201527129ba30b5b2903737ba1032b730b13632b21760711b6044820152606401610c05565b6001546040516348b4573960e11b81523360048201526000918291829182918291829182916001600160a01b031690639168ae729060240160e060405180830381865afa158015611ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1d9190613a76565b96509650965096509650965096506000871115611f925760405162461bcd60e51b815260206004820152602d60248201527f526573746f726520796f757220746f6b656e20746f20746865206e657720636f60448201526c6e7472616374206265666f726560981b6064820152608401610c05565b336000908152601460205260409020600781015460ff16156120005760405162461bcd60e51b815260206004820152602160248201527f46696e69736820726573746f7265206265666f7265207374616b6520616761696044820152603760f91b6064820152608401610c05565b60085415612066576008548154612018908b90613a63565b11156120665760405162461bcd60e51b815260206004820152601860248201527f4d6178207374616b6520616d6f756e74207265616368656400000000000000006044820152606401610c05565b8060050154600003612079574260058201555b80600601546000036120cd576015805460018101825560008290527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec4750180546001600160a01b031916331790555460068201555b600354604051636eb1769f60e11b81523360048201523060248201526000916001600160a01b03169063dd62ed3e90604401602060405180830381865afa15801561211c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121409190613b5b565b9050898110156121625760405162461bcd60e51b8152600401610c0590613b74565b4260018301558154612174908b613336565b8255601154612183908b613336565b6011556003546040516323b872dd60e01b8152336004820152306024820152604481018c90526001600160a01b03909116906323b872dd906064016020604051808303816000875af11580156121dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122019190613ae0565b61221d5760405162461bcd60e51b8152600401610c0590613b2c565b50505050505050505061159f6001600055565b6001600160a01b03811660009081526014602052604081208161225284612723565b601054909150479060ff1680156122695750600082115b80156122755750818110155b80156122845750600954835410155b80156122a05750600a54836001015461229d9190613a63565b42115b8015610d575750600b5483600201546122b99190613a63565b421195945050505050565b6122cc612eae565b336000908152601460205260409020805461231e5760405162461bcd60e51b81526020600482015260126024820152714e6f7468696e6720746f20726573746f726560701b6044820152606401610c05565b600781015460ff166123685760405162461bcd60e51b81526020600482015260136024820152724e6f7420696e20726573746f7265206d6f646560681b6044820152606401610c05565b600354604051636eb1769f60e11b81523360048201523060248201526000916001600160a01b03169063dd62ed3e90604401602060405180830381865afa1580156123b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123db9190613b5b565b82549091508110156123ff5760405162461bcd60e51b8152600401610c0590613b74565b60035482546040516323b872dd60e01b815233600482015230602482015260448101919091526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d9190613ae0565b6124995760405162461bcd60e51b8152600401610c0590613b2c565b60078201805460ff1916905581546011546124b391613336565b60115550506001600055565b60606012805480602002602001604051908101604052809291908181526020016000905b82821015612529578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906124e3565b50505050905090565b6004546001600160a01b031633148061255557506006546001600160a01b031633145b8061256a57506005546001600160a01b031633145b6125865760405162461bcd60e51b8152600401610c05906139b2565b600e55565b6004546001600160a01b03163314806125ae57506006546001600160a01b031633145b806125c357506005546001600160a01b031633145b6125df5760405162461bcd60e51b8152600401610c05906139b2565b6010805491151563010000000263ff00000019909216919091179055565b6004546001600160a01b031633148061262057506006546001600160a01b031633145b8061263557506005546001600160a01b031633145b6126515760405162461bcd60e51b8152600401610c05906139b2565b600855565b6004546001600160a01b031633148061267957506006546001600160a01b031633145b8061268e57506005546001600160a01b031633145b6126aa5760405162461bcd60e51b8152600401610c05906139b2565b601080549115156401000000000264ff0000000019909216919091179055565b6004546001600160a01b03163314806126ed57506006546001600160a01b031633145b8061270257506005546001600160a01b031633145b61271e5760405162461bcd60e51b8152600401610c05906139b2565b601355565b6001600160a01b03811660009081526014602052604081206009548154108061274c5750601154155b806127575750600c54155b15612766576003015492915050565b6000805b6012548110156128e1576012818154811061278757612787613aca565b6000918252602090912060029091020154156128cf5760006127d18460050154601284815481106127ba576127ba613aca565b906000526020600020906002020160010154613342565b905060006127df4283612f0e565b90506000600c5482106127fb5750670de0b6b3a764000061281d565b600c5461281a9061281484670de0b6b3a7640000613358565b90612e06565b90505b601154865460009161283b9161281490670de0b6b3a7640000613358565b90506000612879670de0b6b3a76400006128148460128a8154811061286257612862613aca565b600091825260209091206002909102015490613358565b9050612891670de0b6b3a76400006128148386613358565b905061289c8a611d8a565b6128bd576128ba6064612814600e548461335890919063ffffffff16565b90505b6128c78782613336565b965050505050505b806128d981613afd565b91505061276a565b5060006128fb836005015442612f0e90919063ffffffff16565b90506000600c5482106129175750670de0b6b3a7640000612933565b600c546129309061281484670de0b6b3a7640000613358565b90505b60115484546000916129519161281490670de0b6b3a7640000613358565b90506000612976670de0b6b3a76400006128148460135461335890919063ffffffff16565b905061298e670de0b6b3a76400006128148386613358565b905061299988611d8a565b6129ba576129b76064612814600e548461335890919063ffffffff16565b90505b6129c48582613336565b60038701549095506129d69086613336565b98975050505050505050565b6004546001600160a01b0316331480612a0557506006546001600160a01b031633145b80612a1a57506005546001600160a01b031633145b612a365760405162461bcd60e51b8152600401610c05906139b2565b600a55565b6004546001600160a01b0316331480612a5e57506006546001600160a01b031633145b80612a7357506005546001600160a01b031633145b612a8f5760405162461bcd60e51b8152600401610c05906139b2565b601155565b6004546001600160a01b0316331480612ab757506006546001600160a01b031633145b80612acc57506005546001600160a01b031633145b612ae85760405162461bcd60e51b8152600401610c05906139b2565b61101b60076000613690565b601354600090815b601254811015612b4857612b3460128281548110612b1c57612b1c613aca565b60009182526020909120600290910201548390613336565b915080612b4081613afd565b915050612afc565b50919050565b6004546001600160a01b0316331480612b7157506006546001600160a01b031633145b80612b8657506005546001600160a01b031633145b612ba25760405162461bcd60e51b8152600401610c05906139b2565b600b55565b6001546040516348b4573960e11b81526001600160a01b0383811660048301526000928392839283928392839283928392911690639168ae729060240160e060405180830381865afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c259190613a76565b96509650965096509650965096506000871115612c6c576001600160a01b03891660009081526014602052604090208054612c6a575060019998505050505050505050565b505b50600098975050505050505050565b6004546001600160a01b0316331480612c9e57506006546001600160a01b031633145b80612cb357506005546001600160a01b031633145b612ccf5760405162461bcd60e51b8152600401610c05906139b2565b6040805180820190915234815242602082019081526012805460018101825560009190915291517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600290930292830155517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3445909101556010546301000000900460ff161561101b5761101b613364565b60128181548110612d7057600080fd5b60009182526020909120600290910201805460019091015490915082565b6004546001600160a01b0316331480612db157506006546001600160a01b031633145b80612dc657506005546001600160a01b031633145b612de25760405162461bcd60e51b8152600401610c05906139b2565b6010805461ffff191692151561ff0019169290921761010091151591909102179055565b6000612e128284613bbf565b90505b92915050565b60606000612e2883613597565b600101905060008167ffffffffffffffff811115612e4857612e48613b16565b6040519080825280601f01601f191660200182016040528015612e72576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612e7c57509392505050565b600260005403612f005760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c05565b6002600055565b6001600055565b6000612e128284613be1565b8060005b60125481108015612f2f5750600082115b1561304f5760128181548110612f4757612f47613aca565b60009182526020909120600290910201541561303d578160128281548110612f7157612f71613aca565b90600052602060002090600202016000015411612fe657612fb660128281548110612f9e57612f9e613aca565b60009182526020909120600290910201548390612f0e565b915060128181548110612fcb57612fcb613aca565b6000918252602082206002909102018181556001015561303d565b6130148260128381548110612ffd57612ffd613aca565b600091825260209091206002909102015490612f0e565b6012828154811061302757613027613aca565b6000918252602082206002909102019190915591505b8061304781613afd565b915050612f1e565b5060008111801561306257506000601354115b1561309c5780601354116130885760135461307e908290612f0e565b5050600060135550565b6013546130959082612f0e565b6013555060005b5050565b6001600160a01b0381166000908152601460205260409020600954815410806130c95750601154155b806130d45750600c54155b156130e3574260059091015550565b6000805b60125481101561322a576012818154811061310457613104613aca565b6000918252602090912060029091020154156132185760006131378460050154601284815481106127ba576127ba613aca565b905060006131454283612f0e565b90506000600c5482106131615750670de0b6b3a764000061317d565b600c5461317a9061281484670de0b6b3a7640000613358565b90505b601154865460009161319b9161281490670de0b6b3a7640000613358565b905060006131c2670de0b6b3a76400006128148460128a8154811061286257612862613aca565b90506131da670de0b6b3a76400006128148386613358565b90506131e589611d8a565b613206576132036064612814600e548461335890919063ffffffff16565b90505b6132108782613336565b965050505050505b8061322281613afd565b9150506130e7565b506000613244836005015442612f0e90919063ffffffff16565b90506000600c5482106132605750670de0b6b3a764000061327c565b600c546132799061281484670de0b6b3a7640000613358565b90505b601154845460009161329a9161281490670de0b6b3a7640000613358565b905060006132bf670de0b6b3a76400006128148460135461335890919063ffffffff16565b90506132d7670de0b6b3a76400006128148386613358565b90506132e287611d8a565b613303576133006064612814600e548461335890919063ffffffff16565b90505b61330d8582613336565b600387015490955061331f9086613336565b600387015550504260059094019390935550505050565b6000612e128284613a63565b60008183116133515781612e12565b5090919050565b6000612e128284613bf4565b60125460009067ffffffffffffffff81111561338257613382613b16565b6040519080825280602002602001820160405280156133c757816020015b60408051808201909152600080825260208201528152602001906001900390816133a05790505b5090506000805b6012548110156134d3576000613411601283815481106133f0576133f0613aca565b90600052602060002090600202016001015442612f0e90919063ffffffff16565b9050600c5481106134545761344c6012838154811061343257613432613aca565b600091825260209091206002909102015460135490613336565b6013556134c0565b6012828154811061346757613467613aca565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508484815181106134a6576134a6613aca565b602002602001018190525082806134bc90613afd565b9350505b50806134cb81613afd565b9150506133ce565b50801561358b57601254811461309c575b6012548110156135225760128054806134ff576134ff613c0b565b6000828152602081206002600019909301928302018181556001015590556134e4565b60005b81811015611b965782818151811061353f5761353f613aca565b60200260200101516012828154811061355a5761355a613aca565b600091825260209182902083516002909202019081559101516001909101558061358381613afd565b915050613525565b61309c6012600061366f565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106135d65772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310613602576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061362057662386f26fc10000830492506010015b6305f5e1008310613638576305f5e100830492506008015b612710831061364c57612710830492506004015b6064831061365e576064830492506002015b600a8310612e155760010192915050565b508054600082556002029060005260206000209081019061159f91906136b1565b508054600082556002029060005260206000209081019061159f91906136d0565b5b808211156136cc57600080825560018201556002016136b2565b5090565b5b808211156136cc5780546001600160a01b0319908116825560018201805490911690556002016136d1565b60006020828403121561370e57600080fd5b5035919050565b801515811461159f57600080fd5b60006020828403121561373557600080fd5b813561374081613715565b9392505050565b80356001600160a01b038116811461375e57600080fd5b919050565b60006020828403121561377557600080fd5b612e1282613747565b60005b83811015613799578181015183820152602001613781565b50506000910152565b60208152600082518060208401526137c181604085016020870161377e565b601f01601f19169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b818110156138165783516001600160a01b0316835292840192918401916001016137f1565b50909695505050505050565b6000806040838503121561383557600080fd5b50508035926020909101359150565b6000806020838503121561385757600080fd5b823567ffffffffffffffff8082111561386f57600080fd5b818501915085601f83011261388357600080fd5b81358181111561389257600080fd5b8660208260051b85010111156138a757600080fd5b60209290920196919550909350505050565b600080600080600080600080610100898b0312156138d657600080fd5b6138df89613747565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c0890135915060e089013561391981613715565b809150509295985092959890939650565b602080825282518282018190526000919060409081850190868401855b8281101561396c57815180518552860151868501529284019290850190600101613947565b5091979650505050505050565b6000806040838503121561398c57600080fd5b823561399781613715565b915060208301356139a781613715565b809150509250929050565b60208082526018908201527f4e6f742074686520726577617264732070726f76696465720000000000000000604082015260600190565b7f546f20626520656c696769626c652c20796f75206861766520746f207374616b81527503290309036b4b734b6bab690122920ab22a71037b3160551b602082015260008251613a4081603685016020870161377e565b9190910160360192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115612e1557612e15613a4d565b600080600080600080600060e0888a031215613a9157600080fd5b5050855160208701516040880151606089015160808a015160a08b015160c0909b0151949c939b50919990985090965094509092509050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613af257600080fd5b815161374081613715565b600060018201613b0f57613b0f613a4d565b5060010190565b634e487b7160e01b600052604160045260246000fd5b602080825260159082015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b600060208284031215613b6d57600080fd5b5051919050565b6020808252602b908201527f416c6c6f77616e6365206973206e6f742073756666696369656e7420746f207360408201526a74616b6520746f6b656e7360a81b606082015260800190565b600082613bdc57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115612e1557612e15613a4d565b8082028115828204841417612e1557612e15613a4d565b634e487b7160e01b600052603160045260246000fdfe596f7520646f6e2774206861766520616e792072657761726420746f20636c61696d20666f7220746865206d6f6d656e742e506c656173652077616974206e65772066756e647320746f20636c61696d20796f7572207265776172642e436c61696d206e6f7420656e61626c65642c20706c6561736520776169742061206d6f6d656e742ea26469706673582212203b4e95dac3593199a80bae625b926683b8143a6b69f79c4696cc7f12042b573664736f6c63430008130033

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

00000000000000000000000043af0944b34ad466dcea7fc8f77aafc6a4ec70fa000000000000000000000000d7cd7131a6e558bc71ec4e3ae39074d6cb0882c60000000000000000000000008892c1843e632b9649e0cc8ad09e26c0198f7e30

-----Decoded View---------------
Arg [0] : _stakingToken (address): 0x43aF0944b34ad466DceA7FC8f77AAfc6a4Ec70fa
Arg [1] : _rewardsProvider (address): 0xD7cD7131a6e558BC71EC4E3Ae39074d6Cb0882C6
Arg [2] : _teamWallet (address): 0x8892C1843e632B9649e0cC8AD09E26c0198f7e30

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000043af0944b34ad466dcea7fc8f77aafc6a4ec70fa
Arg [1] : 000000000000000000000000d7cd7131a6e558bc71ec4e3ae39074d6cb0882c6
Arg [2] : 0000000000000000000000008892c1843e632b9649e0cc8ad09e26c0198f7e30


Deployed Bytecode Sourcemap

63201:21780:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83746:110;;;;;;;;;;-1:-1:-1;83746:110:0;;;;;:::i;:::-;;:::i;:::-;;64050:31;;;;;;;;;;-1:-1:-1;64050:31:0;;;;;;;;;;;;;;364:14:1;;357:22;339:41;;327:2;312:18;64050:31:0;;;;;;;;83864:107;;;;;;;;;;-1:-1:-1;83864:107:0;;;;;:::i;:::-;;:::i;63777:39::-;;;;;;;;;;;;;;;;;;;906:25:1;;;894:2;879:18;63777:39:0;760:177:1;70179:1172:0;;;;;;;;;;-1:-1:-1;70179:1172:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;64130:38::-;;;;;;;;;;-1:-1:-1;64130:38:0;;;;;;;;;;;68265:705;;;;;;;;;;;;;:::i;63340:41::-;;;;;;;;;;-1:-1:-1;63340:41:0;;;;-1:-1:-1;;;;;63340:41:0;;;;;;-1:-1:-1;;;;;2131:32:1;;;2113:51;;2101:2;2086:18;63340:41:0;1967:203:1;82760:96:0;;;;;;;;;;-1:-1:-1;82760:96:0;;;;;:::i;:::-;;:::i;79082:279::-;;;;;;;;;;;;;:::i;64012:31::-;;;;;;;;;;-1:-1:-1;64012:31:0;;;;;;;;63421:30;;;;;;;;;;-1:-1:-1;63421:30:0;;;;-1:-1:-1;;;;;63421:30:0;;;81060:691;;;;;;;;;;-1:-1:-1;81060:691:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;66773:936::-;;;;;;;;;;-1:-1:-1;66773:936:0;;;;;:::i;:::-;;:::i;64662:36::-;;;;;;;;;;;;;;;;64088:35;;;;;;;;;;-1:-1:-1;64088:35:0;;;;;;;;;;;63731:39;;;;;;;;;;;;;;;;64759:32;;;;;;;;;;-1:-1:-1;64759:32:0;;;;;:::i;:::-;;:::i;83356:118::-;;;;;;;;;;-1:-1:-1;83356:118:0;;;;;:::i;:::-;;:::i;79369:107::-;;;;;;;;;;;;;:::i;71359:1044::-;;;;;;;;;;;;;:::i;64503:32::-;;;;;;;;;;;;;;;;63458:25;;;;;;;;;;-1:-1:-1;63458:25:0;;;;-1:-1:-1;;;;;63458:25:0;;;63640:33;;;;;;;;;;;;;;;;82630:122;;;;;;;;;;-1:-1:-1;82630:122:0;;;;;:::i;:::-;;:::i;84778:200::-;;;;;;;;;;-1:-1:-1;84778:200:0;;;;;:::i;:::-;;:::i;81960:391::-;;;;;;;;;;-1:-1:-1;81960:391:0;;;;;:::i;:::-;;:::i;63388:26::-;;;;;;;;;;-1:-1:-1;63388:26:0;;;;-1:-1:-1;;;;;63388:26:0;;;84333:437;;;;;;;;;;-1:-1:-1;84333:437:0;;;;;:::i;:::-;;:::i;63823:41::-;;;;;;;;;;;;;;;;63517:27;;;;;;;;;;-1:-1:-1;63517:27:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;4936:15:1;;;4918:34;;4988:15;;;;4983:2;4968:18;;4961:43;4853:18;63517:27:0;4667:343:1;63490:20:0;;;;;;;;;;-1:-1:-1;63490:20:0;;;;-1:-1:-1;;;;;63490:20:0;;;64707:45;;;;;;;;;;-1:-1:-1;64707:45:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5352:25:1;;;5408:2;5393:18;;5386:34;;;;5436:18;;;5429:34;;;;5494:2;5479:18;;5472:34;;;;5537:3;5522:19;;5515:35;5581:3;5566:19;;5559:35;5625:3;5610:19;;5603:35;5682:14;5675:22;5669:3;5654:19;;5647:51;5339:3;5324:19;64707:45:0;5015:689:1;82988:116:0;;;;;;;;;;-1:-1:-1;82988:116:0;;;;;:::i;:::-;;:::i;83614:124::-;;;;;;;;;;-1:-1:-1;83614:124:0;;;;;:::i;:::-;;:::i;81759:96::-;;;;;;;;;;;;;:::i;80776:276::-;;;;;;;;;;-1:-1:-1;80776:276:0;;;;;:::i;:::-;;:::i;65343:1422::-;;;;;;;;;;-1:-1:-1;65343:1422:0;;;;;:::i;:::-;;:::i;63680:44::-;;;;;;;;;;;;;;;;63290:43;;;;;;;;;;-1:-1:-1;63290:43:0;;;;-1:-1:-1;;;;;63290:43:0;;;69678:493;;;;;;;;;;-1:-1:-1;69678:493:0;;;;;:::i;:::-;;:::i;64175:34::-;;;;;;;;;;-1:-1:-1;64175:34:0;;;;;;;;;;;68978:692;;;;;;;;;;;;;:::i;79484:107::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;63922:39::-;;;;;;;;;;;;;;;;83482:124;;;;;;;;;;-1:-1:-1;83482:124:0;;;;;:::i;:::-;;:::i;83979:113::-;;;;;;;;;;-1:-1:-1;83979:113:0;;;;;:::i;:::-;;:::i;82864:116::-;;;;;;;;;;-1:-1:-1;82864:116:0;;;;;:::i;:::-;;:::i;63871:44::-;;;;;;;;;;;;;;;;84100:105;;;;;;;;;;-1:-1:-1;84100:105:0;;;;;:::i;:::-;;:::i;84213:112::-;;;;;;;;;;-1:-1:-1;84213:112:0;;;;;:::i;:::-;;:::i;72411:2470::-;;;;;;;;;;-1:-1:-1;72411:2470:0;;;;;:::i;:::-;;:::i;83112:110::-;;;;;;;;;;-1:-1:-1;83112:110:0;;;;;:::i;:::-;;:::i;82500:122::-;;;;;;;;;;-1:-1:-1;82500:122:0;;;;;:::i;:::-;;:::i;81863:89::-;;;;;;;;;;;;;:::i;78449:309::-;;;;;;;;;;;;;:::i;63968:35::-;;;;;;;;;;;;;;;;83230:118;;;;;;;;;;-1:-1:-1;83230:118:0;;;;;:::i;:::-;;:::i;67717:540::-;;;;;;;;;;-1:-1:-1;67717:540:0;;;;;:::i;:::-;;:::i;78803:271::-;;;:::i;64628:27::-;;;;;;;;;;-1:-1:-1;64628:27:0;;;;;:::i;:::-;;:::i;:::-;;;;6906:25:1;;;6962:2;6947:18;;6940:34;;;;6879:18;64628:27:0;6732:248:1;82359:133:0;;;;;;;;;;-1:-1:-1;82359:133:0;;;;;:::i;:::-;;:::i;83746:110::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;;;;;;;;;83827:16:::1;:21:::0;83746:110::o;83864:107::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83942:16:::1;:21:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;83942:21:0;;::::1;::::0;;;::::1;::::0;;83864:107::o;70179:1172::-;-1:-1:-1;;;;;70298:22:0;;70270:25;70298:22;;;:7;:22;;;;;70244:13;;70348:35;70306:13;70348:20;:35::i;:::-;70457:11;;70331:52;;-1:-1:-1;70420:21:0;;70457:11;;70452:93;;70484:49;;;;;;;;;;;;;;;;;;70179:1172;-1:-1:-1;;;;;70179:1172:0:o;70452:93::-;70581:14;;70559:19;;:36;70555:205;;;70718:14;;70701:45;;70718:27;;70737:7;70718:18;:27::i;:::-;70701:16;:45::i;:::-;70626:121;;;;;;;;:::i;:::-;;;;;;;;;;;;;70612:136;;;;;70179:1172;;;:::o;70555:205::-;70816:13;;70793:6;:20;;;:36;;;;:::i;:::-;70774:15;:55;70770:149;;70853:54;70893:13;;70870:6;:20;;;:36;;;;:::i;70853:54::-;70846:61;70179:1172;-1:-1:-1;;;;;70179:1172:0:o;70770:149::-;70975:13;;70952:6;:20;;;:36;;;;:::i;:::-;70933:15;:55;70929:149;;71012:54;71052:13;;71029:6;:20;;;:36;;;;:::i;70929:149::-;71102:1;71092:6;:11;71088:102;;71119:59;;;;;;;;;;;;;;;;;;70179:1172;-1:-1:-1;;;;;70179:1172:0:o;71088:102::-;71222:6;71204:15;:24;71200:109;;;71245:52;;;;;;;;;;;;;;;;;;70179:1172;-1:-1:-1;;;;;70179:1172:0:o;71200:109::-;-1:-1:-1;;71319:24:0;;;;;;;;;;;;-1:-1:-1;;;71319:24:0;;;;;70179:1172;-1:-1:-1;;;70179:1172:0:o;68265:705::-;44752:21;:19;:21::i;:::-;68330:22:::1;68341:10;68330;:22::i;:::-;68322:58;;;::::0;-1:-1:-1;;;68322:58:0;;8705:2:1;68322:58:0::1;::::0;::::1;8687:21:1::0;8744:2;8724:18;;;8717:30;-1:-1:-1;;;8763:18:1;;;8756:53;8826:18;;68322:58:0::1;8503:347:1::0;68322:58:0::1;68399:15;::::0;;;::::1;;;68391:51;;;::::0;-1:-1:-1;;;68391:51:0;;8705:2:1;68391:51:0::1;::::0;::::1;8687:21:1::0;8744:2;8724:18;;;8717:30;-1:-1:-1;;;8763:18:1;;;8756:53;8826:18;;68391:51:0::1;8503:347:1::0;68391:51:0::1;68619:18;::::0;:38:::1;::::0;-1:-1:-1;;;68619:38:0;;68646:10:::1;68619:38;::::0;::::1;2113:51:1::0;68454:20:0::1;::::0;;;;;;;;;;;;;-1:-1:-1;;;;;68619:18:0::1;::::0;:26:::1;::::0;2086:18:1;;68619:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68692:123;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68810:4:::1;68692:123:::0;;;;;;68678:10:::1;-1:-1:-1::0;68670:19:0;;;:7:::1;:19:::0;;;;;;;:145;;;;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;68670:145:0::1;::::0;::::1;;::::0;;;::::1;::::0;;;68826:15:::1;:32:::0;;;;::::1;::::0;;;;;::::1;::::0;;-1:-1:-1;;;;;;68826:32:0::1;::::0;;::::1;::::0;;;68900:22;68869:53;;-1:-1:-1;44796:20:0;;-1:-1:-1;44796:18:0;;-1:-1:-1;;;;;44796:20:0:i;:::-;68265:705::o;82760:96::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;82834:5:::1;:14:::0;;-1:-1:-1;;;;;;82834:14:0::1;-1:-1:-1::0;;;;;82834:14:0;;;::::1;::::0;;;::::1;::::0;;82760:96::o;79082:279::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;79165:21:::1;79205:11:::0;79197:44:::1;;;::::0;-1:-1:-1;;;79197:44:0;;9616:2:1;79197:44:0::1;::::0;::::1;9598:21:1::0;9655:2;9635:18;;;9628:30;-1:-1:-1;;;9674:18:1;;;9667:50;9734:18;;79197:44:0::1;9414:344:1::0;79197:44:0::1;79252:37;::::0;79260:10:::1;::::0;79252:37;::::1;;;::::0;79281:7;;79252:37:::1;::::0;;;79281:7;79260:10;79252:37;::::1;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;79302:19:0::1;79309:12;;79302:19;:::i;:::-;-1:-1:-1::0;79352:1:0::1;79332:17;:21:::0;79082:279::o;81060:691::-;81123:16;81152:19;81191:9;81186:172;81210:10;:17;81206:21;;81186:172;;;81253:10;81264:1;81253:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;:44;;-1:-1:-1;;;81253:44:0;;-1:-1:-1;;;;;2131:32:1;;;81253:44:0;;;2113:51:1;81253:22:0;;;;:37;;2086:18:1;;81253:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81249:98;;;81318:13;;;;:::i;:::-;;;;81249:98;81229:3;;;;:::i;:::-;;;;81186:172;;;;81368:37;81422:11;81408:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81408:26:0;;81368:66;;81447:9;81476;81471:233;81495:10;:17;81491:21;;81471:233;;;81538:10;81549:1;81538:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;:44;;-1:-1:-1;;;81538:44:0;;-1:-1:-1;;;;;2131:32:1;;;81538:44:0;;;2113:51:1;81538:22:0;;;;:37;;2086:18:1;;81538:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81534:159;;;81637:10;81648:1;81637:13;;;;;;;;:::i;:::-;;;;;;;;;;;:17;;;;;;;;;;-1:-1:-1;;;;;81637:17:0;81603:20;81624:1;81603:23;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81603:52:0;;;:23;;;;;;;;;;;:52;81674:3;;;;:::i;:::-;;;;81534:159;81514:3;;;;:::i;:::-;;;;81471:233;;;-1:-1:-1;81723:20:0;;81060:691;-1:-1:-1;;;;81060:691:0:o;66773:936::-;44752:21;:19;:21::i;:::-;66876:10:::1;66840:25;66868:19:::0;;;:7:::1;:19;::::0;;;;66908:10;66900:52:::1;;;::::0;-1:-1:-1;;;66900:52:0;;10619:2:1;66900:52:0::1;::::0;::::1;10601:21:1::0;10658:2;10638:18;;;10631:30;10697:31;10677:18;;;10670:59;10746:18;;66900:52:0::1;10417:353:1::0;66900:52:0::1;66971:19:::0;;:29;-1:-1:-1;66971:29:0::1;66963:68;;;::::0;-1:-1:-1;;;66963:68:0;;10977:2:1;66963:68:0::1;::::0;::::1;10959:21:1::0;11016:2;10996:18;;;10989:30;11055:28;11035:18;;;11028:56;11101:18;;66963:68:0::1;10775:350:1::0;66963:68:0::1;67066:19:::0;;:31:::1;::::0;67090:6;67066:23:::1;:31::i;:::-;67044:53:::0;;67128:17:::1;::::0;:29:::1;::::0;67150:6;67128:21:::1;:29::i;:::-;67108:17;:49:::0;67174:19;;67170:444:::1;;67232:20;::::0;::::1;::::0;;67215:14:::1;67267:24:::0;;;67329:15:::1;67306:20;::::0;::::1;:38:::0;67385:21:::1;67425:10:::0;;;;;:39:::1;;;67458:6;67439:15;:25;;67425:39;:59;;;;-1:-1:-1::0;67468:16:0::1;::::0;;;::::1;;;67425:59;67421:182;;;67504:26;67523:6;67504:18;:26::i;:::-;67559:10;::::0;67551:36:::1;::::0;-1:-1:-1;;;;;67559:10:0;;::::1;::::0;67551:36;::::1;;;::::0;67580:6;;67559:10:::1;67551:36:::0;67559:10;67551:36;67580:6;67559:10;67551:36;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;67421:182;67200:414;;67170:444;67634:12;::::0;:41:::1;::::0;-1:-1:-1;;;67634:41:0;;67656:10:::1;67634:41;::::0;::::1;11304:51:1::0;11371:18;;;11364:34;;;-1:-1:-1;;;;;67634:12:0;;::::1;::::0;:21:::1;::::0;11277:18:1;;67634:41:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67626:75;;;;-1:-1:-1::0;;;67626:75:0::1;;;;;;;:::i;:::-;66829:880;44796:20:::0;44190:1;45316:7;:22;45133:213;44796:20;66773:936;:::o;64759:32::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;64759:32:0;;-1:-1:-1;64759:32:0;:::o;83356:118::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83441:17:::1;:25:::0;83356:118::o;79369:107::-;79417:16;79453:15;79446:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;79446:22:0;;;;;;;;;;;;;;;;;;;;;;;79369:107;:::o;71359:1044::-;44752:21;:19;:21::i;:::-;71417:11:::1;::::0;::::1;;71409:42;;;::::0;-1:-1:-1;;;71409:42:0;;11961:2:1;71409:42:0::1;::::0;::::1;11943:21:1::0;12000:2;11980:18;;;11973:30;-1:-1:-1;;;12019:18:1;;;12012:48;12077:18;;71409:42:0::1;11759:342:1::0;71409:42:0::1;71498:10;71462:25;71490:19:::0;;;:7:::1;:19;::::0;;;;71551:14:::1;::::0;71528:19;;:37:::1;;71520:84;;;::::0;-1:-1:-1;;;71520:84:0;;12308:2:1;71520:84:0::1;::::0;::::1;12290:21:1::0;12347:2;12327:18;;;12320:30;12386:34;12366:18;;;12359:62;-1:-1:-1;;;12437:18:1;;;12430:32;12479:19;;71520:84:0::1;12106:398:1::0;71520:84:0::1;71664:13;;71641:6;:20;;;:36;;;;:::i;:::-;71623:15;:54;71615:93;;;::::0;-1:-1:-1;;;71615:93:0;;12711:2:1;71615:93:0::1;::::0;::::1;12693:21:1::0;12750:2;12730:18;;;12723:30;12789:28;12769:18;;;12762:56;12835:18;;71615:93:0::1;12509:350:1::0;71615:93:0::1;71768:13;;71745:6;:20;;;:36;;;;:::i;:::-;71727:15;:54;71719:91;;;::::0;-1:-1:-1;;;71719:91:0;;13066:2:1;71719:91:0::1;::::0;::::1;13048:21:1::0;13105:2;13085:18;;;13078:30;13144:26;13124:18;;;13117:54;13188:18;;71719:91:0::1;12864:348:1::0;71719:91:0::1;71823:31;71843:10;71823:19;:31::i;:::-;71884:20;::::0;::::1;::::0;71923:10;71915:43:::1;;;::::0;-1:-1:-1;;;71915:43:0;;13419:2:1;71915:43:0::1;::::0;::::1;13401:21:1::0;13458:2;13438:18;;;13431:30;-1:-1:-1;;;13477:18:1;;;13470:50;13537:18;;71915:43:0::1;13217:344:1::0;71915:43:0::1;71997:21;72037:25:::0;;::::1;;72029:68;;;::::0;-1:-1:-1;;;72029:68:0;;13768:2:1;72029:68:0::1;::::0;::::1;13750:21:1::0;13807:2;13787:18;;;13780:30;13846:32;13826:18;;;13819:60;13896:18;;72029:68:0::1;13566:354:1::0;72029:68:0::1;72110:26;72129:6;72110:18;:26::i;:::-;72170:1;72147:20;::::0;::::1;:24:::0;72205:15:::1;72182:20;::::0;::::1;:38:::0;72255:21:::1;::::0;::::1;::::0;:33:::1;::::0;72281:6;72255:25:::1;:33::i;:::-;72231:21;::::0;::::1;:57:::0;72318:16:::1;::::0;:28:::1;::::0;72339:6;72318:20:::1;:28::i;:::-;72299:16;:47:::0;72359:36:::1;::::0;72367:10:::1;::::0;72359:36;::::1;;;::::0;72388:6;;72359:36:::1;::::0;;;72388:6;72367:10;72359:36;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;71398:1005;;;44796:20:::0;44190:1;45316:7;:22;45133:213;82630:122;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;82717:15:::1;:27:::0;;-1:-1:-1;;;;;;82717:27:0::1;-1:-1:-1::0;;;;;82717:27:0;;;::::1;::::0;;;::::1;::::0;;82630:122::o;84778:200::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;84892:77:::1;::::0;;;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;84874:12:::1;:96:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;84874:96:0;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;84778:200::o;81960:391::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;82066:6:::1;82061:283;82078:19:::0;;::::1;82061:283;;;82119:21;82143:8;;82152:1;82143:11;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;;;;;;;;;;82203:45:0;;::::1;::::0;;;-1:-1:-1;;;82263:33:0;;;82311:10:::1;:21:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;82311:21:0;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;;82311:21:0;;::::1;;::::0;;;;;;;;;;;;;::::1;::::0;::::1;;::::0;;-1:-1:-1;82099:3:0;::::1;::::0;::::1;:::i;:::-;;;;82061:283;;;;81960:391:::0;;:::o;84333:437::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;84487:10:0;;;::::1;;::::0;;;:7:::1;:10;::::0;;;;:32;;;84530:24:::1;::::0;::::1;:29:::0;;;;84570:24:::1;::::0;::::1;:29:::0;;;;84610:24:::1;::::0;::::1;:29:::0;84650:25:::1;::::0;::::1;:30:::0;84691:31:::1;::::0;::::1;:36:::0;84738:20:::1;;:24:::0;;-1:-1:-1;;84738:24:0::1;::::0;::::1;;::::0;;;::::1;::::0;;84333:437::o;63517:27::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63517:27:0;;;;-1:-1:-1;63517:27:0;;:::o;82988:116::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83072:14:::1;:24:::0;82988:116::o;83614:124::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83702:19:::1;:28:::0;83614:124::o;81759:96::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;81828:19:::1;81835:12;;81828:19;:::i;80776:276::-:0;80835:4;;80852:170;80876:10;:17;80872:21;;80852:170;;;80919:10;80930:1;80919:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;:44;;-1:-1:-1;;;80919:44:0;;-1:-1:-1;;;;;2131:32:1;;;80919:44:0;;;2113:51:1;80919:22:0;;;;:37;;2086:18:1;;80919:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80915:96;;;-1:-1:-1;80991:4:0;;80776:276;-1:-1:-1;;80776:276:0:o;80915:96::-;80895:3;;;;:::i;:::-;;;;80852:170;;;-1:-1:-1;81039:5:0;;80776:276;-1:-1:-1;;80776:276:0:o;65343:1422::-;44752:21;:19;:21::i;:::-;65415:11:::1;::::0;::::1;::::0;::::1;;;65407:42;;;::::0;-1:-1:-1;;;65407:42:0;;14127:2:1;65407:42:0::1;::::0;::::1;14109:21:1::0;14166:2;14146:18;;;14139:30;-1:-1:-1;;;14185:18:1;;;14178:48;14243:18;;65407:42:0::1;13925:342:1::0;65407:42:0::1;65626:18;::::0;:38:::1;::::0;-1:-1:-1;;;65626:38:0;;65653:10:::1;65626:38;::::0;::::1;2113:51:1::0;65461:20:0::1;::::0;;;;;;;;;;;;;-1:-1:-1;;;;;65626:18:0::1;::::0;:26:::1;::::0;2086:18:1;;65626:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65460:204;;;;;;;;;;;;;;65699:1;65683:12;:17;;65675:75;;;::::0;-1:-1:-1;;;65675:75:0;;14474:2:1;65675:75:0::1;::::0;::::1;14456:21:1::0;14513:2;14493:18;;;14486:30;14552:34;14532:18;;;14525:62;-1:-1:-1;;;14603:18:1;;;14596:43;14656:19;;65675:75:0::1;14272:409:1::0;65675:75:0::1;65797:10;65761:25;65789:19:::0;;;:7:::1;:19;::::0;;;;65827:16:::1;::::0;::::1;::::0;::::1;;:25;65819:71;;;::::0;-1:-1:-1;;;65819:71:0;;14888:2:1;65819:71:0::1;::::0;::::1;14870:21:1::0;14927:2;14907:18;;;14900:30;14966:34;14946:18;;;14939:62;-1:-1:-1;;;15017:18:1;;;15010:31;15058:19;;65819:71:0::1;14686:397:1::0;65819:71:0::1;65905:14;::::0;:18;65901:134:::1;;65980:14;::::0;65948:19;;:28:::1;::::0;65970:6;;65948:28:::1;:::i;:::-;:46;;65940:83;;;::::0;-1:-1:-1;;;65940:83:0;;15290:2:1;65940:83:0::1;::::0;::::1;15272:21:1::0;15329:2;15309:18;;;15302:30;15368:26;15348:18;;;15341:54;15412:18;;65940:83:0::1;15088:348:1::0;65940:83:0::1;66051:6;:27;;;66082:1;66051:32:::0;66047:110:::1;;66130:15;66100:27;::::0;::::1;:45:::0;66047:110:::1;66173:6;:15;;;66192:1;66173:20:::0;66169:139:::1;;66209:15;:32:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;66209:32:0;;;;::::1;::::0;;-1:-1:-1;;;;;;66209:32:0::1;66230:10;66209:32;::::0;;66274:22;66256:15:::1;::::0;::::1;:40:::0;66169:139:::1;66340:12;::::0;:49:::1;::::0;-1:-1:-1;;;66340:49:0;;66363:10:::1;66340:49;::::0;::::1;4918:34:1::0;66383:4:0::1;4968:18:1::0;;;4961:43;66320:17:0::1;::::0;-1:-1:-1;;;;;66340:12:0::1;::::0;:22:::1;::::0;4853:18:1;;66340:49:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66320:69;;66421:6;66408:9;:19;;66400:75;;;;-1:-1:-1::0;;;66400:75:0::1;;;;;;;:::i;:::-;66511:15;66488:20;::::0;::::1;:38:::0;66559:19;;:31:::1;::::0;66583:6;66559:23:::1;:31::i;:::-;66537:53:::0;;66621:17:::1;::::0;:29:::1;::::0;66643:6;66621:21:::1;:29::i;:::-;66601:17;:49:::0;66671:12:::1;::::0;:60:::1;::::0;-1:-1:-1;;;66671:60:0;;66697:10:::1;66671:60;::::0;::::1;16591:34:1::0;66717:4:0::1;16641:18:1::0;;;16634:43;16693:18;;;16686:34;;;-1:-1:-1;;;;;66671:12:0;;::::1;::::0;:25:::1;::::0;16526:18:1;;66671:60:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66663:94;;;;-1:-1:-1::0;;;66663:94:0::1;;;;;;;:::i;:::-;65396:1369;;;;;;;;;44796:20:::0;44190:1;45316:7;:22;45133:213;69678:493;-1:-1:-1;;;;;69785:22:0;;69740:4;69785:22;;;:7;:22;;;;;69740:4;69835:35;69793:13;69835:20;:35::i;:::-;69946:11;;69818:52;;-1:-1:-1;69907:21:0;;69946:11;;:25;;;;;69970:1;69961:6;:10;69946:25;:54;;;;;69994:6;69975:15;:25;;69946:54;:97;;;;-1:-1:-1;70028:14:0;;70005:19;;:37;;69946:97;:157;;;;;70089:13;;70066:6;:20;;;:36;;;;:::i;:::-;70048:15;:54;69946:157;:217;;;;;70149:13;;70126:6;:20;;;:36;;;;:::i;:::-;70108:15;:54;69939:224;69678:493;-1:-1:-1;;;;;69678:493:0:o;68978:692::-;44752:21;:19;:21::i;:::-;69116:10:::1;69080:25;69108:19:::0;;;:7:::1;:19;::::0;;;;69146;;69138:54:::1;;;::::0;-1:-1:-1;;;69138:54:0;;16933:2:1;69138:54:0::1;::::0;::::1;16915:21:1::0;16972:2;16952:18;;;16945:30;-1:-1:-1;;;16991:18:1;;;16984:48;17049:18;;69138:54:0::1;16731:342:1::0;69138:54:0::1;69211:16;::::0;::::1;::::0;::::1;;69203:48;;;::::0;-1:-1:-1;;;69203:48:0;;17280:2:1;69203:48:0::1;::::0;::::1;17262:21:1::0;17319:2;17299:18;;;17292:30;-1:-1:-1;;;17338:18:1;;;17331:49;17397:18;;69203:48:0::1;17078:343:1::0;69203:48:0::1;69284:12;::::0;:49:::1;::::0;-1:-1:-1;;;69284:49:0;;69307:10:::1;69284:49;::::0;::::1;4918:34:1::0;69327:4:0::1;4968:18:1::0;;;4961:43;69264:17:0::1;::::0;-1:-1:-1;;;;;69284:12:0::1;::::0;:22:::1;::::0;4853:18:1;;69284:49:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69365:19:::0;;69264:69;;-1:-1:-1;69352:32:0;::::1;;69344:88;;;;-1:-1:-1::0;;;69344:88:0::1;;;;;;;:::i;:::-;69453:12;::::0;69506:19;;69453:73:::1;::::0;-1:-1:-1;;;69453:73:0;;69479:10:::1;69453:73;::::0;::::1;16591:34:1::0;69499:4:0::1;16641:18:1::0;;;16634:43;16693:18;;;16686:34;;;;-1:-1:-1;;;;;69453:12:0;;::::1;::::0;:25:::1;::::0;16526:18:1;;69453:73:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69445:107;;;;-1:-1:-1::0;;;69445:107:0::1;;;;;;;:::i;:::-;69565:16;::::0;::::1;:24:::0;;-1:-1:-1;;69565:24:0::1;::::0;;69642:19;;69620:17:::1;::::0;:42:::1;::::0;:21:::1;:42::i;:::-;69600:17;:62:::0;-1:-1:-1;;44190:1:0;45316:7;:22;68265:705::o;79484:107::-;79537:14;79571:12;79564:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79484:107;:::o;83482:124::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83570:19:::1;:28:::0;83482:124::o;83979:113::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;84060:19:::1;:24:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;84060:24:0;;::::1;::::0;;;::::1;::::0;;83979:113::o;82864:116::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;82948:14:::1;:24:::0;82864:116::o;84100:105::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;84177:15:::1;:20:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;84177:20:0;;::::1;::::0;;;::::1;::::0;;84100:105::o;84213:112::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;84295:17:::1;:22:::0;84213:112::o;72411:2470::-;-1:-1:-1;;;;;72533:22:0;;72485:7;72533:22;;;:7;:22;;;;;72594:14;;72572:19;;:36;;:62;;-1:-1:-1;72612:17:0;;:22;72572:62;:88;;;-1:-1:-1;72638:17:0;;:22;72572:88;72568:148;;;72684:20;;;;72411:2470;-1:-1:-1;;72411:2470:0:o;72568:148::-;72728:19;72766:9;72762:1104;72785:12;:19;72781:23;;72762:1104;;;72830:12;72843:1;72830:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;72826:76;72878:8;72826:76;72916:21;72940:61;72944:6;:27;;;72973:12;72986:1;72973:15;;;;;;;;:::i;:::-;;;;;;;;;;;:27;;;72940:3;:61::i;:::-;72916:85;-1:-1:-1;73016:19:0;73038:34;:15;72916:85;73038:19;:34::i;:::-;73016:56;;73101:18;73152:17;;73137:11;:32;73134:193;;-1:-1:-1;73203:7:0;73134:193;;;73293:17;;73264:47;;:24;:11;73280:7;73264:15;:24::i;:::-;:28;;:47::i;:::-;73251:60;;73134:193;73414:17;;73377:19;;73355;;73377:55;;:32;;73401:7;73377:23;:32::i;:55::-;73355:77;;73447:29;73479:52;73523:7;73479:39;73506:11;73479:12;73492:1;73479:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;;:26;:39::i;:52::-;73447:84;-1:-1:-1;73570:50:0;73612:7;73570:37;73447:84;73596:10;73570:25;:37::i;:50::-;73546:74;;73642:28;73656:13;73642;:28::i;:::-;73637:149;;73715:55;73766:3;73715:46;73741:19;;73715:21;:25;;:46;;;;:::i;:55::-;73691:79;;73637:149;73816:38;:11;73832:21;73816:15;:38::i;:::-;73802:52;;72811:1055;;;;;72762:1104;72806:3;;;;:::i;:::-;;;;72762:1104;;;;73929:31;73963:48;73983:6;:27;;;73963:15;:19;;:48;;;;:::i;:::-;73929:82;;74022:30;74093:17;;74066:23;:44;74063:225;;-1:-1:-1;74152:7:0;74063:225;;;74258:17;;74217:59;;:36;:23;74245:7;74217:27;:36::i;:59::-;74192:84;;74063:225;74373:17;;74336:19;;74298:35;;74336:55;;:32;;74360:7;74336:23;:32::i;:55::-;74298:93;;74402:30;74435:63;74490:7;74435:50;74457:27;74435:17;;:21;;:50;;;;:::i;:63::-;74402:96;-1:-1:-1;74534:63:0;74589:7;74534:50;74402:96;74561:22;74534:26;:50::i;:63::-;74509:88;;74613:28;74627:13;74613;:28::i;:::-;74608:143;;74683:56;74735:3;74683:47;74710:19;;74683:22;:26;;:47;;;;:::i;:56::-;74658:81;;74608:143;74777:39;:11;74793:22;74777:15;:39::i;:::-;74836:20;;;;74763:53;;-1:-1:-1;74836:37:0;;74763:53;74836:24;:37::i;:::-;74829:44;72411:2470;-1:-1:-1;;;;;;;;72411:2470:0:o;83112:110::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83193:13:::1;:21:::0;83112:110::o;82500:122::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;82587:17:::1;:27:::0;82500:122::o;81863:89::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;81927:17:::1;81934:10;;81927:17;:::i;78449:309::-:0;78551:17;;78506:7;;;78581:136;78605:12;:19;78601:23;;78581:136;;;78663:42;78682:12;78695:1;78682:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;78663:14;;:18;:42::i;:::-;78646:59;-1:-1:-1;78626:3:0;;;;:::i;:::-;;;;78581:136;;;-1:-1:-1;78736:14:0;78449:309;-1:-1:-1;78449:309:0:o;83230:118::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;83315:13:::1;:25:::0;83230:118::o;67717:540::-;67964:18;;:41;;-1:-1:-1;;;67964:41:0;;-1:-1:-1;;;;;2131:32:1;;;67964:41:0;;;2113:51:1;67781:4:0;;;;;;;;;;;;;;;;67964:18;;;:26;;2086:18:1;;67964:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67798:207;;;;;;;;;;;;;;68035:1;68020:12;:16;68016:211;;;-1:-1:-1;;;;;68090:22:0;;68062:25;68090:22;;;:7;:22;;;;;68131:19;;68127:89;;-1:-1:-1;68196:4:0;;67717:540;-1:-1:-1;;;;;;;;;67717:540:0:o;68127:89::-;68047:180;68016:211;-1:-1:-1;68244:5:0;;67717:540;-1:-1:-1;;;;;;;;67717:540:0:o;78803:271::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;78891:93:::1;::::0;;;;::::1;::::0;;;78920:9:::1;78891:93:::0;;78957:15:::1;78891:93;::::0;::::1;::::0;;;78873:12:::1;:112:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;78873:112:0;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;79002:19:::1;::::0;;;::::1;;;78998:69;;;79037:18;:16;:18::i;64628:27::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64628:27:0;:::o;82359:133::-;65220:15;;-1:-1:-1;;;;;65220:15:0;65206:10;:29;;:52;;-1:-1:-1;65253:5:0;;-1:-1:-1;;;;;65253:5:0;65239:10;:19;65206:52;:80;;;-1:-1:-1;65276:10:0;;-1:-1:-1;;;;;65276:10:0;65262;:24;65206:80;65198:117;;;;-1:-1:-1;;;65198:117:0;;;;;;;:::i;:::-;82441:11:::1;:16:::0;;-1:-1:-1;;82468:16:0;82441;::::1;;-1:-1:-1::0;;82468:16:0;;;;;82441::::1;82468::::0;::::1;;::::0;;;::::1;;::::0;;82359:133::o;49660:98::-;49718:7;49745:5;49749:1;49745;:5;:::i;:::-;49738:12;;49660:98;;;;;:::o;14920:716::-;14976:13;15027:14;15044:17;15055:5;15044:10;:17::i;:::-;15064:1;15044:21;15027:38;;15080:20;15114:6;15103:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15103:18:0;-1:-1:-1;15080:41:0;-1:-1:-1;15245:28:0;;;15261:2;15245:28;15302:288;-1:-1:-1;;15334:5:0;-1:-1:-1;;;15471:2:0;15460:14;;15455:30;15334:5;15442:44;15532:2;15523:11;;;-1:-1:-1;15553:21:0;15302:288;15553:21;-1:-1:-1;15611:6:0;14920:716;-1:-1:-1;;;14920:716:0:o;44832:293::-;44234:1;44966:7;;:19;44958:63;;;;-1:-1:-1;;;44958:63:0;;17982:2:1;44958:63:0;;;17964:21:1;18021:2;18001:18;;;17994:30;18060:33;18040:18;;;18033:61;18111:18;;44958:63:0;17780:355:1;44958:63:0;44234:1;45099:7;:18;44832:293::o;45133:213::-;44190:1;45316:7;:22;45133:213::o;48904:98::-;48962:7;48989:5;48993:1;48989;:5;:::i;79713:1055::-;79804:6;79776:25;79821:532;79845:12;:19;79841:23;;:48;;;;;79888:1;79868:17;:21;79841:48;79821:532;;;79915:12;79928:1;79915:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;79911:76;79963:8;79911:76;80031:17;80005:12;80018:1;80005:15;;;;;;;;:::i;:::-;;;;;;;;;;;:22;;;:43;80001:341;;80089:45;80111:12;80124:1;80111:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;80089:17;;:21;:45::i;:::-;80069:65;;80160:12;80173:1;80160:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;80153:22;;;;;;80001:341;;;80241:45;80268:17;80241:12;80254:1;80241:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;;:26;:45::i;:::-;80216:12;80229:1;80216:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;:70;;;;:15;-1:-1:-1;80001:341:0;79891:3;;;;:::i;:::-;;;;79821:532;;;;80387:1;80367:17;:21;:46;;;;;80412:1;80392:17;;:21;80367:46;80363:398;;;80455:17;80434;;:38;80430:320;;80535:17;;80513:40;;:17;;:21;:40::i;:::-;-1:-1:-1;;80592:1:0;80572:17;:21;-1:-1:-1;79713:1055:0:o;80430:320::-;80654:17;;:40;;80676:17;80654:21;:40::i;:::-;80634:17;:60;-1:-1:-1;80733:1:0;80430:320;79765:1003;79713:1055;:::o;74889:2557::-;-1:-1:-1;;;;;74989:22:0;;74961:25;74989:22;;;:7;:22;;;;;75050:14;;75028:19;;:36;;:62;;-1:-1:-1;75068:17:0;;:22;75028:62;:88;;;-1:-1:-1;75094:17:0;;:22;75028:88;75024:187;;;75163:15;75133:27;;;;:45;-1:-1:-1;74889:2557:0:o;75024:187::-;75223:19;75261:9;75257:1104;75280:12;:19;75276:23;;75257:1104;;;75325:12;75338:1;75325:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;75321:76;75373:8;75321:76;75411:21;75435:61;75439:6;:27;;;75468:12;75481:1;75468:15;;;;;;;;:::i;75435:61::-;75411:85;-1:-1:-1;75511:19:0;75533:34;:15;75411:85;75533:19;:34::i;:::-;75511:56;;75596:18;75647:17;;75632:11;:32;75629:193;;-1:-1:-1;75698:7:0;75629:193;;;75788:17;;75759:47;;:24;:11;75775:7;75759:15;:24::i;:47::-;75746:60;;75629:193;75909:17;;75872:19;;75850;;75872:55;;:32;;75896:7;75872:23;:32::i;:55::-;75850:77;;75942:29;75974:52;76018:7;75974:39;76001:11;75974:12;75987:1;75974:15;;;;;;;;:::i;:52::-;75942:84;-1:-1:-1;76065:50:0;76107:7;76065:37;75942:84;76091:10;76065:25;:37::i;:50::-;76041:74;;76137:28;76151:13;76137;:28::i;:::-;76132:149;;76210:55;76261:3;76210:46;76236:19;;76210:21;:25;;:46;;;;:::i;:55::-;76186:79;;76132:149;76311:38;:11;76327:21;76311:15;:38::i;:::-;76297:52;;75306:1055;;;;;75257:1104;75301:3;;;;:::i;:::-;;;;75257:1104;;;;76424:31;76458:48;76478:6;:27;;;76458:15;:19;;:48;;;;:::i;:::-;76424:82;;76517:30;76588:17;;76561:23;:44;76558:225;;-1:-1:-1;76647:7:0;76558:225;;;76753:17;;76712:59;;:36;:23;76740:7;76712:27;:36::i;:59::-;76687:84;;76558:225;76868:17;;76831:19;;76793:35;;76831:55;;:32;;76855:7;76831:23;:32::i;:55::-;76793:93;;76897:30;76930:63;76985:7;76930:50;76952:27;76930:17;;:21;;:50;;;;:::i;:63::-;76897:96;-1:-1:-1;77029:63:0;77084:7;77029:50;76897:96;77056:22;77029:26;:50::i;:63::-;77004:88;;77108:28;77122:13;77108;:28::i;:::-;77103:143;;77178:56;77230:3;77178:47;77205:19;;77178:22;:26;;:47;;;;:::i;:56::-;77153:81;;77103:143;77272:39;:11;77288:22;77272:15;:39::i;:::-;77345:20;;;;77258:53;;-1:-1:-1;77345:37:0;;77258:53;77345:24;:37::i;:::-;77322:20;;;:60;-1:-1:-1;;77423:15:0;77393:27;;;;:45;;;;-1:-1:-1;;;;74889:2557:0:o;48523:98::-;48581:7;48608:5;48612:1;48608;:5;:::i;79599:106::-;79657:7;79688:1;79684;:5;:13;;79696:1;79684:13;;;-1:-1:-1;79692:1:0;;79599:106;-1:-1:-1;79599:106:0:o;49261:98::-;49319:7;49346:5;49350:1;49346;:5;:::i;77454:987::-;77546:12;:19;77501:30;;77534:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;77534:32:0;;;;;;;;;;;;;;;;77501:65;;77579:13;77612:9;77607:406;77631:12;:19;77627:23;;77607:406;;;77672:19;77694:48;77714:12;77727:1;77714:15;;;;;;;;:::i;:::-;;;;;;;;;;;:27;;;77694:15;:19;;:48;;;;:::i;:::-;77672:70;;77776:17;;77761:11;:32;77757:245;;77834:45;77856:12;77869:1;77856:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;77834:17;;;:21;:45::i;:::-;77814:17;:65;77757:245;;;77945:12;77958:1;77945:15;;;;;;;;:::i;:::-;;;;;;;;;;;77920:40;;;;;;;;;;;;;;;;;;;;;;;;;:15;77936:5;77920:22;;;;;;;;:::i;:::-;;;;;;:40;;;;77979:7;;;;;:::i;:::-;;;;77757:245;-1:-1:-1;77652:3:0;;;;:::i;:::-;;;;77607:406;;;-1:-1:-1;78029:9:0;;78025:409;;78059:12;:19;:28;;78055:316;;78108:97;78115:12;:19;:27;-1:-1:-1;78108:97:0;;;78167:12;:18;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;78167:18:0;;;;;;;;;;;;;;;78108:97;;;78246:9;78241:115;78265:5;78261:1;:9;78241:115;;;78318:15;78334:1;78318:18;;;;;;;;:::i;:::-;;;;;;;78300:12;78313:1;78300:15;;;;;;;;:::i;:::-;;;;;;;;;;:36;;:15;;;;;:36;;;;;;;;;;;78272:3;;;;:::i;:::-;;;;78241:115;;78025:409;78403:19;78410:12;;78403:19;:::i;11754:948::-;11807:7;;-1:-1:-1;;;11885:17:0;;11881:106;;-1:-1:-1;;;11923:17:0;;;-1:-1:-1;11969:2:0;11959:12;11881:106;12014:8;12005:5;:17;12001:106;;12052:8;12043:17;;;-1:-1:-1;12089:2:0;12079:12;12001:106;12134:8;12125:5;:17;12121:106;;12172:8;12163:17;;;-1:-1:-1;12209:2:0;12199:12;12121:106;12254:7;12245:5;:16;12241:103;;12291:7;12282:16;;;-1:-1:-1;12327:1:0;12317:11;12241:103;12371:7;12362:5;:16;12358:103;;12408:7;12399:16;;;-1:-1:-1;12444:1:0;12434:11;12358:103;12488:7;12479:5;:16;12475:103;;12525:7;12516:16;;;-1:-1:-1;12561:1:0;12551:11;12475:103;12605:7;12596:5;:16;12592:68;;12643:1;12633:11;12688:6;11754:948;-1:-1:-1;;11754:948:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:180:1;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;391:118::-;477:5;470:13;463:21;456:5;453:32;443:60;;499:1;496;489:12;514:241;570:6;623:2;611:9;602:7;598:23;594:32;591:52;;;639:1;636;629:12;591:52;678:9;665:23;697:28;719:5;697:28;:::i;:::-;744:5;514:241;-1:-1:-1;;;514:241:1:o;942:173::-;1010:20;;-1:-1:-1;;;;;1059:31:1;;1049:42;;1039:70;;1105:1;1102;1095:12;1039:70;942:173;;;:::o;1120:186::-;1179:6;1232:2;1220:9;1211:7;1207:23;1203:32;1200:52;;;1248:1;1245;1238:12;1200:52;1271:29;1290:9;1271:29;:::i;1311:250::-;1396:1;1406:113;1420:6;1417:1;1414:13;1406:113;;;1496:11;;;1490:18;1477:11;;;1470:39;1442:2;1435:10;1406:113;;;-1:-1:-1;;1553:1:1;1535:16;;1528:27;1311:250::o;1566:396::-;1715:2;1704:9;1697:21;1678:4;1747:6;1741:13;1790:6;1785:2;1774:9;1770:18;1763:34;1806:79;1878:6;1873:2;1862:9;1858:18;1853:2;1845:6;1841:15;1806:79;:::i;:::-;1946:2;1925:15;-1:-1:-1;;1921:29:1;1906:45;;;;1953:2;1902:54;;1566:396;-1:-1:-1;;1566:396:1:o;2175:658::-;2346:2;2398:21;;;2468:13;;2371:18;;;2490:22;;;2317:4;;2346:2;2569:15;;;;2543:2;2528:18;;;2317:4;2612:195;2626:6;2623:1;2620:13;2612:195;;;2691:13;;-1:-1:-1;;;;;2687:39:1;2675:52;;2782:15;;;;2747:12;;;;2723:1;2641:9;2612:195;;;-1:-1:-1;2824:3:1;;2175:658;-1:-1:-1;;;;;;2175:658:1:o;2838:248::-;2906:6;2914;2967:2;2955:9;2946:7;2942:23;2938:32;2935:52;;;2983:1;2980;2973:12;2935:52;-1:-1:-1;;3006:23:1;;;3076:2;3061:18;;;3048:32;;-1:-1:-1;2838:248:1:o;3091:615::-;3177:6;3185;3238:2;3226:9;3217:7;3213:23;3209:32;3206:52;;;3254:1;3251;3244:12;3206:52;3294:9;3281:23;3323:18;3364:2;3356:6;3353:14;3350:34;;;3380:1;3377;3370:12;3350:34;3418:6;3407:9;3403:22;3393:32;;3463:7;3456:4;3452:2;3448:13;3444:27;3434:55;;3485:1;3482;3475:12;3434:55;3525:2;3512:16;3551:2;3543:6;3540:14;3537:34;;;3567:1;3564;3557:12;3537:34;3620:7;3615:2;3605:6;3602:1;3598:14;3594:2;3590:23;3586:32;3583:45;3580:65;;;3641:1;3638;3631:12;3580:65;3672:2;3664:11;;;;;3694:6;;-1:-1:-1;3091:615:1;;-1:-1:-1;;;;3091:615:1:o;3934:728::-;4053:6;4061;4069;4077;4085;4093;4101;4109;4162:3;4150:9;4141:7;4137:23;4133:33;4130:53;;;4179:1;4176;4169:12;4130:53;4202:29;4221:9;4202:29;:::i;:::-;4192:39;;4278:2;4267:9;4263:18;4250:32;4240:42;;4329:2;4318:9;4314:18;4301:32;4291:42;;4380:2;4369:9;4365:18;4352:32;4342:42;;4431:3;4420:9;4416:19;4403:33;4393:43;;4483:3;4472:9;4468:19;4455:33;4445:43;;4535:3;4524:9;4520:19;4507:33;4497:43;;4590:3;4579:9;4575:19;4562:33;4604:28;4626:5;4604:28;:::i;:::-;4651:5;4641:15;;;3934:728;;;;;;;;;;;:::o;5943:784::-;6160:2;6212:21;;;6282:13;;6185:18;;;6304:22;;;6131:4;;6160:2;6345;;6363:18;;;;6404:15;;;6131:4;6447:254;6461:6;6458:1;6455:13;6447:254;;;6520:13;;6558:9;;6546:22;;6608:11;;6602:18;6588:12;;;6581:40;6641:12;;;;6676:15;;;;6483:1;6476:9;6447:254;;;-1:-1:-1;6718:3:1;;5943:784;-1:-1:-1;;;;;;;5943:784:1:o;6985:376::-;7047:6;7055;7108:2;7096:9;7087:7;7083:23;7079:32;7076:52;;;7124:1;7121;7114:12;7076:52;7163:9;7150:23;7182:28;7204:5;7182:28;:::i;:::-;7229:5;-1:-1:-1;7286:2:1;7271:18;;7258:32;7299:30;7258:32;7299:30;:::i;:::-;7348:7;7338:17;;;6985:376;;;;;:::o;7366:348::-;7568:2;7550:21;;;7607:2;7587:18;;;7580:30;7646:26;7641:2;7626:18;;7619:54;7705:2;7690:18;;7366:348::o;7719:517::-;7981:34;7976:3;7969:47;-1:-1:-1;;;8041:2:1;8036:3;8032:12;8025:46;7951:3;8100:6;8094:13;8116:73;8182:6;8177:2;8172:3;8168:12;8163:2;8155:6;8151:15;8116:73;:::i;:::-;8209:16;;;;8227:2;8205:25;;7719:517;-1:-1:-1;;7719:517:1:o;8241:127::-;8302:10;8297:3;8293:20;8290:1;8283:31;8333:4;8330:1;8323:15;8357:4;8354:1;8347:15;8373:125;8438:9;;;8459:10;;;8456:36;;;8472:18;;:::i;8855:554::-;8979:6;8987;8995;9003;9011;9019;9027;9080:3;9068:9;9059:7;9055:23;9051:33;9048:53;;;9097:1;9094;9087:12;9048:53;-1:-1:-1;;9120:16:1;;9176:2;9161:18;;9155:25;9220:2;9205:18;;9199:25;9264:2;9249:18;;9243:25;9308:3;9293:19;;9287:26;9353:3;9338:19;;9332:26;9398:3;9383:19;;;9377:26;9120:16;;9155:25;;-1:-1:-1;9199:25:1;;9243;;-1:-1:-1;9287:26:1;;-1:-1:-1;9332:26:1;-1:-1:-1;9377:26:1;;-1:-1:-1;8855:554:1;-1:-1:-1;8855:554:1:o;9763:127::-;9824:10;9819:3;9815:20;9812:1;9805:31;9855:4;9852:1;9845:15;9879:4;9876:1;9869:15;9895:245;9962:6;10015:2;10003:9;9994:7;9990:23;9986:32;9983:52;;;10031:1;10028;10021:12;9983:52;10063:9;10057:16;10082:28;10104:5;10082:28;:::i;10145:135::-;10184:3;10205:17;;;10202:43;;10225:18;;:::i;:::-;-1:-1:-1;10272:1:1;10261:13;;10145:135::o;10285:127::-;10346:10;10341:3;10337:20;10334:1;10327:31;10377:4;10374:1;10367:15;10401:4;10398:1;10391:15;11409:345;11611:2;11593:21;;;11650:2;11630:18;;;11623:30;-1:-1:-1;;;11684:2:1;11669:18;;11662:51;11745:2;11730:18;;11409:345::o;15750:184::-;15820:6;15873:2;15861:9;15852:7;15848:23;15844:32;15841:52;;;15889:1;15886;15879:12;15841:52;-1:-1:-1;15912:16:1;;15750:184;-1:-1:-1;15750:184:1:o;15939:407::-;16141:2;16123:21;;;16180:2;16160:18;;;16153:30;16219:34;16214:2;16199:18;;16192:62;-1:-1:-1;;;16285:2:1;16270:18;;16263:41;16336:3;16321:19;;15939:407::o;17558:217::-;17598:1;17624;17614:132;;17668:10;17663:3;17659:20;17656:1;17649:31;17703:4;17700:1;17693:15;17731:4;17728:1;17721:15;17614:132;-1:-1:-1;17760:9:1;;17558:217::o;18140:128::-;18207:9;;;18228:11;;;18225:37;;;18242:18;;:::i;18273:168::-;18346:9;;;18377;;18394:15;;;18388:22;;18374:37;18364:71;;18415:18;;:::i;18446:127::-;18507:10;18502:3;18498:20;18495:1;18488:31;18538:4;18535:1;18528:15;18562:4;18559:1;18552:15

Swarm Source

ipfs://3b4e95dac3593199a80bae625b926683b8143a6b69f79c4696cc7f12042b5736

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.