S Price: $0.504248 (-0.59%)

Contract

0xCc94f67DA67311B187407979EE94cD7b52c8F270

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ProtocolGovernor

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at SonicScan.org on 2024-12-18
*/

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
// OpenZeppelin Contracts (last updated v4.8.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) {
                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);
        }
    }
}
// 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);
        }
    }
}
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}
pragma solidity 0.8.19;

/// @title SafeCast Library
/// @author velodrome.finance
/// @notice Safely convert unsigned and signed integers without overflow / underflow
library SafeCastLibrary {
    error SafeCastOverflow();
    error SafeCastUnderflow();

    /// @dev Safely convert uint256 to int128
    function toInt128(uint256 value) internal pure returns (int128) {
        if (value > uint128(type(int128).max)) revert SafeCastOverflow();
        return int128(uint128(value));
    }

    /// @dev Safely convert int128 to uint256
    function toUint256(int128 value) internal pure returns (uint256) {
        if (value < 0) revert SafeCastUnderflow();
        return uint256(int256(value));
    }
}
pragma solidity 0.8.19;

library ProtocolTimeLibrary {
    uint256 internal constant WEEK = 7 days;

    /// @dev Returns start of epoch based on current timestamp
    function epochStart(uint256 timestamp) internal pure returns (uint256) {
        unchecked {
            return timestamp - (timestamp % WEEK);
        }
    }

    /// @dev Returns start of next epoch / end of current epoch
    function epochNext(uint256 timestamp) internal pure returns (uint256) {
        unchecked {
            return timestamp - (timestamp % WEEK) + WEEK;
        }
    }

    /// @dev Returns start of voting window
    function epochVoteStart(uint256 timestamp) internal pure returns (uint256) {
        unchecked {
            return timestamp - (timestamp % WEEK) + 1 hours;
        }
    }

    /// @dev Returns end of voting window / beginning of unrestricted voting window
    function epochVoteEnd(uint256 timestamp) internal pure returns (uint256) {
        unchecked {
            return timestamp - (timestamp % WEEK) + WEEK - 1 hours;
        }
    }
}
pragma solidity ^0.8.0;

interface IReward {
    error InvalidReward();
    error NotAuthorized();
    error NotGauge();
    error NotEscrowToken();
    error NotSingleToken();
    error NotVotingEscrow();
    error NotWhitelisted();
    error ZeroAmount();

    event Deposit(address indexed from, uint256 indexed tokenId, uint256 amount);
    event Withdraw(address indexed from, uint256 indexed tokenId, uint256 amount);
    event NotifyReward(address indexed from, address indexed reward, uint256 indexed epoch, uint256 amount);
    event ClaimRewards(address indexed from, address indexed reward, uint256 amount);

    /// @notice A checkpoint for marking balance
    struct Checkpoint {
        uint256 timestamp;
        uint256 balanceOf;
    }

    /// @notice A checkpoint for marking supply
    struct SupplyCheckpoint {
        uint256 timestamp;
        uint256 supply;
    }

    /// @notice Epoch duration constant (7 days)
    function DURATION() external view returns (uint256);

    /// @notice Address of Voter.sol
    function voter() external view returns (address);

    /// @notice Address of VotingEscrow.sol
    function ve() external view returns (address);

    /// @dev Address which has permission to externally call _deposit() & _withdraw()
    function authorized() external view returns (address);

    /// @notice Total amount currently deposited via _deposit()
    function totalSupply() external view returns (uint256);

    /// @notice Current amount deposited by tokenId
    function balanceOf(uint256 tokenId) external view returns (uint256);

    /// @notice Amount of tokens to reward depositors for a given epoch
    /// @param token Address of token to reward
    /// @param epochStart Startime of rewards epoch
    /// @return Amount of token
    function tokenRewardsPerEpoch(address token, uint256 epochStart) external view returns (uint256);

    /// @notice Most recent timestamp a veNFT has claimed their rewards
    /// @param  token Address of token rewarded
    /// @param tokenId veNFT unique identifier
    /// @return Timestamp
    function lastEarn(address token, uint256 tokenId) external view returns (uint256);

    /// @notice True if a token is or has been an active reward token, else false
    function isReward(address token) external view returns (bool);

    /// @notice The number of checkpoints for each tokenId deposited
    function numCheckpoints(uint256 tokenId) external view returns (uint256);

    /// @notice The total number of checkpoints
    function supplyNumCheckpoints() external view returns (uint256);

    /// @notice Deposit an amount into the rewards contract to earn future rewards associated to a veNFT
    /// @dev Internal notation used as only callable internally by `authorized`.
    /// @param amount   Amount deposited for the veNFT
    /// @param tokenId  Unique identifier of the veNFT
    function _deposit(uint256 amount, uint256 tokenId) external;

    /// @notice Withdraw an amount from the rewards contract associated to a veNFT
    /// @dev Internal notation used as only callable internally by `authorized`.
    /// @param amount   Amount deposited for the veNFT
    /// @param tokenId  Unique identifier of the veNFT
    function _withdraw(uint256 amount, uint256 tokenId) external;

    /// @notice Claim the rewards earned by a veNFT staker
    /// @param tokenId  Unique identifier of the veNFT
    /// @param tokens   Array of tokens to claim rewards of
    function getReward(uint256 tokenId, address[] memory tokens) external;

    /// @notice Add rewards for stakers to earn
    /// @param token    Address of token to reward
    /// @param amount   Amount of token to transfer to rewards
    function notifyRewardAmount(address token, uint256 amount) external;

    /// @notice Determine the prior balance for an account as of a block number
    /// @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
    /// @param tokenId      The token of the NFT to check
    /// @param timestamp    The timestamp to get the balance at
    /// @return The balance the account had as of the given block
    function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp) external view returns (uint256);

    /// @notice Determine the prior index of supply staked by of a timestamp
    /// @dev Timestamp must be <= current timestamp
    /// @param timestamp The timestamp to get the index at
    /// @return Index of supply checkpoint
    function getPriorSupplyIndex(uint256 timestamp) external view returns (uint256);

    /// @notice Get number of rewards tokens
    function rewardsListLength() external view returns (uint256);

    /// @notice Calculate how much in rewards are earned for a specific token and veNFT
    /// @param token Address of token to fetch rewards of
    /// @param tokenId Unique identifier of the veNFT
    /// @return Amount of token earned in rewards
    function earned(address token, uint256 tokenId) external view returns (uint256);

    function checkpoints(uint256 tokenId, uint256 index) external view returns (uint256 timestamp, uint256 balanceOf);

    function supplyCheckpoints(uint256 index) external view returns (uint256 timestamp, uint256 supply);
}
pragma solidity ^0.8.0;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

pragma solidity ^0.8.8;

type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 * Strings of arbitrary length can be optimized if they are short enough by
 * the addition of a storage variable used as fallback.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    error StringTooLong(string str);

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = length(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function length(ShortString sstr) internal pure returns (uint256) {
        return uint256(ShortString.unwrap(sstr)) & 0xFF;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(0);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (length(value) > 0) {
            return toString(value);
        } else {
            return store;
        }
    }
}
// OpenZeppelin Contracts (last updated v4.8.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));
    }
}
// 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);
}
// OpenZeppelin Contracts (last updated v4.8.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);
}
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Checkpoints.sol)
// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.

pragma solidity ^0.8.0;

/**
 * @dev This library defines the `History` struct, for checkpointing values as they change at different points in
 * time, and later looking up past values by block number. See {Votes} as an example.
 *
 * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new
 * checkpoint for the current transaction block using the {push} function.
 *
 * _Available since v4.5._
 */
library Checkpoints {
    struct History {
        Checkpoint[] _checkpoints;
    }

    struct Checkpoint {
        uint32 _blockNumber;
        uint224 _value;
    }

    /**
     * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
     * before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
     * block, the requested block number must be in the past, excluding the current block.
     */
    function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
        require(blockNumber < block.number, "Checkpoints: block not yet mined");
        uint32 key = SafeCast.toUint32(blockNumber);

        uint256 len = self._checkpoints.length;
        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
     * before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
     * checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
     * checkpoints.
     */
    function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
        require(blockNumber < block.number, "Checkpoints: block not yet mined");
        uint32 key = SafeCast.toUint32(blockNumber);

        uint256 len = self._checkpoints.length;

        uint256 low = 0;
        uint256 high = len;

        if (len > 5) {
            uint256 mid = len - Math.sqrt(len);
            if (key < _unsafeAccess(self._checkpoints, mid)._blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);

        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
     *
     * Returns previous value and new value.
     */
    function push(History storage self, uint256 value) internal returns (uint256, uint256) {
        return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
    }

    /**
     * @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
     * be set to `op(latest, delta)`.
     *
     * Returns previous value and new value.
     */
    function push(
        History storage self,
        function(uint256, uint256) view returns (uint256) op,
        uint256 delta
    ) internal returns (uint256, uint256) {
        return push(self, op(latest(self), delta));
    }

    /**
     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
     */
    function latest(History storage self) internal view returns (uint224) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
     * in the most recent checkpoint.
     */
    function latestCheckpoint(
        History storage self
    ) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) {
        uint256 pos = self._checkpoints.length;
        if (pos == 0) {
            return (false, 0, 0);
        } else {
            Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
            return (true, ckpt._blockNumber, ckpt._value);
        }
    }

    /**
     * @dev Returns the number of checkpoint.
     */
    function length(History storage self) internal view returns (uint256) {
        return self._checkpoints.length;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
     * or by updating the last one.
     */
    function _insert(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
        uint256 pos = self.length;

        if (pos > 0) {
            // Copying to memory is important here.
            Checkpoint memory last = _unsafeAccess(self, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require(last._blockNumber <= key, "Checkpoint: decreasing keys");

            // Update or push new checkpoint
            if (last._blockNumber == key) {
                _unsafeAccess(self, pos - 1)._value = value;
            } else {
                self.push(Checkpoint({_blockNumber: key, _value: value}));
            }
            return (last._value, value);
        } else {
            self.push(Checkpoint({_blockNumber: key, _value: value}));
            return (0, value);
        }
    }

    /**
     * @dev Return the index of the oldest checkpoint whose key is greater than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _upperBinaryLookup(
        Checkpoint[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._blockNumber > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * @dev Return the index of the oldest checkpoint whose key is greater or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _lowerBinaryLookup(
        Checkpoint[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._blockNumber < key) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return high;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }

    struct Trace224 {
        Checkpoint224[] _checkpoints;
    }

    struct Checkpoint224 {
        uint32 _key;
        uint224 _value;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.
     *
     * Returns previous value and new value.
     */
    function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) {
        return _insert(self._checkpoints, key, value);
    }

    /**
     * @dev Returns the value in the oldest checkpoint with key greater or equal than the search key, or zero if there is none.
     */
    function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint with key lower or equal than the search key.
     */
    function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint with key lower or equal than the search key.
     *
     * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
     */
    function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {
        uint256 len = self._checkpoints.length;

        uint256 low = 0;
        uint256 high = len;

        if (len > 5) {
            uint256 mid = len - Math.sqrt(len);
            if (key < _unsafeAccess(self._checkpoints, mid)._key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);

        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
     */
    function latest(Trace224 storage self) internal view returns (uint224) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
     * in the most recent checkpoint.
     */
    function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {
        uint256 pos = self._checkpoints.length;
        if (pos == 0) {
            return (false, 0, 0);
        } else {
            Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
            return (true, ckpt._key, ckpt._value);
        }
    }

    /**
     * @dev Returns the number of checkpoint.
     */
    function length(Trace224 storage self) internal view returns (uint256) {
        return self._checkpoints.length;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
     * or by updating the last one.
     */
    function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
        uint256 pos = self.length;

        if (pos > 0) {
            // Copying to memory is important here.
            Checkpoint224 memory last = _unsafeAccess(self, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require(last._key <= key, "Checkpoint: decreasing keys");

            // Update or push new checkpoint
            if (last._key == key) {
                _unsafeAccess(self, pos - 1)._value = value;
            } else {
                self.push(Checkpoint224({_key: key, _value: value}));
            }
            return (last._value, value);
        } else {
            self.push(Checkpoint224({_key: key, _value: value}));
            return (0, value);
        }
    }

    /**
     * @dev Return the index of the oldest checkpoint whose key is greater than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _upperBinaryLookup(
        Checkpoint224[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * @dev Return the index of the oldest checkpoint whose key is greater or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _lowerBinaryLookup(
        Checkpoint224[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key < key) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return high;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(
        Checkpoint224[] storage self,
        uint256 pos
    ) private pure returns (Checkpoint224 storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }

    struct Trace160 {
        Checkpoint160[] _checkpoints;
    }

    struct Checkpoint160 {
        uint96 _key;
        uint160 _value;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.
     *
     * Returns previous value and new value.
     */
    function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) {
        return _insert(self._checkpoints, key, value);
    }

    /**
     * @dev Returns the value in the oldest checkpoint with key greater or equal than the search key, or zero if there is none.
     */
    function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint with key lower or equal than the search key.
     */
    function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint with key lower or equal than the search key.
     *
     * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
     */
    function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {
        uint256 len = self._checkpoints.length;

        uint256 low = 0;
        uint256 high = len;

        if (len > 5) {
            uint256 mid = len - Math.sqrt(len);
            if (key < _unsafeAccess(self._checkpoints, mid)._key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);

        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
     */
    function latest(Trace160 storage self) internal view returns (uint160) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
     * in the most recent checkpoint.
     */
    function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {
        uint256 pos = self._checkpoints.length;
        if (pos == 0) {
            return (false, 0, 0);
        } else {
            Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
            return (true, ckpt._key, ckpt._value);
        }
    }

    /**
     * @dev Returns the number of checkpoint.
     */
    function length(Trace160 storage self) internal view returns (uint256) {
        return self._checkpoints.length;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
     * or by updating the last one.
     */
    function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) {
        uint256 pos = self.length;

        if (pos > 0) {
            // Copying to memory is important here.
            Checkpoint160 memory last = _unsafeAccess(self, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require(last._key <= key, "Checkpoint: decreasing keys");

            // Update or push new checkpoint
            if (last._key == key) {
                _unsafeAccess(self, pos - 1)._value = value;
            } else {
                self.push(Checkpoint160({_key: key, _value: value}));
            }
            return (last._value, value);
        } else {
            self.push(Checkpoint160({_key: key, _value: value}));
            return (0, value);
        }
    }

    /**
     * @dev Return the index of the oldest checkpoint whose key is greater than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _upperBinaryLookup(
        Checkpoint160[] storage self,
        uint96 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * @dev Return the index of the oldest checkpoint whose key is greater or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _lowerBinaryLookup(
        Checkpoint160[] storage self,
        uint96 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key < key) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return high;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(
        Checkpoint160[] storage self,
        uint256 pos
    ) private pure returns (Checkpoint160 storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }
}
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}
// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)
pragma solidity ^0.8.4;

/**
 * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
 * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
 * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
 * the existing queue contents are left in storage.
 *
 * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be
 * used in storage, and not in memory.
 * ```solidity
 * DoubleEndedQueue.Bytes32Deque queue;
 * ```
 *
 * _Available since v4.6._
 */
library DoubleEndedQueue {
    /**
     * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
     */
    error Empty();

    /**
     * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
     */
    error OutOfBounds();

    /**
     * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end
     * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely
     * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.
     *
     * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
     * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
     * lead to unexpected behavior.
     *
     * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at
     * data[end - 1].
     */
    struct Bytes32Deque {
        int128 _begin;
        int128 _end;
        mapping(int128 => bytes32) _data;
    }

    /**
     * @dev Inserts an item at the end of the queue.
     */
    function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
        int128 backIndex = deque._end;
        deque._data[backIndex] = value;
        unchecked {
            deque._end = backIndex + 1;
        }
    }

    /**
     * @dev Removes the item at the end of the queue and returns it.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 backIndex;
        unchecked {
            backIndex = deque._end - 1;
        }
        value = deque._data[backIndex];
        delete deque._data[backIndex];
        deque._end = backIndex;
    }

    /**
     * @dev Inserts an item at the beginning of the queue.
     */
    function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
        int128 frontIndex;
        unchecked {
            frontIndex = deque._begin - 1;
        }
        deque._data[frontIndex] = value;
        deque._begin = frontIndex;
    }

    /**
     * @dev Removes the item at the beginning of the queue and returns it.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 frontIndex = deque._begin;
        value = deque._data[frontIndex];
        delete deque._data[frontIndex];
        unchecked {
            deque._begin = frontIndex + 1;
        }
    }

    /**
     * @dev Returns the item at the beginning of the queue.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 frontIndex = deque._begin;
        return deque._data[frontIndex];
    }

    /**
     * @dev Returns the item at the end of the queue.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 backIndex;
        unchecked {
            backIndex = deque._end - 1;
        }
        return deque._data[backIndex];
    }

    /**
     * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
     * `length(deque) - 1`.
     *
     * Reverts with `OutOfBounds` if the index is out of bounds.
     */
    function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
        // int256(deque._begin) is a safe upcast
        int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));
        if (idx >= deque._end) revert OutOfBounds();
        return deque._data[idx];
    }

    /**
     * @dev Resets the queue back to being empty.
     *
     * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
     * out on potential gas refunds.
     */
    function clear(Bytes32Deque storage deque) internal {
        deque._begin = 0;
        deque._end = 0;
    }

    /**
     * @dev Returns the number of items in the queue.
     */
    function length(Bytes32Deque storage deque) internal view returns (uint256) {
        // The interface preserves the invariant that begin <= end so we assume this will not overflow.
        // We also assume there are at most int256.max items in the queue.
        unchecked {
            return uint256(int256(deque._end) - int256(deque._begin));
        }
    }

    /**
     * @dev Returns true if the queue is empty.
     */
    function empty(Bytes32Deque storage deque) internal view returns (bool) {
        return deque._end <= deque._begin;
    }
}
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

pragma solidity ^0.8.0;

/// @title EIP-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
// OpenZeppelin Contracts (interfaces/IERC6372.sol)

pragma solidity ^0.8.0;

interface IERC6372 {
    /**
     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
     */
    function clock() external view returns (uint48);

    /**
     * @dev Description of the clock
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() external view returns (string memory);
}
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}
pragma solidity ^0.8.0;

interface IVoter {
    error AlreadyVotedOrDeposited();
    error DistributeWindow();
    error FactoryPathNotApproved();
    error GaugeAlreadyKilled();
    error GaugeAlreadyRevived();
    error GaugeExists();
    error GaugeDoesNotExist(address _pool);
    error GaugeNotAlive(address _gauge);
    error InactiveManagedNFT();
    error MaximumVotingNumberTooLow();
    error NonZeroVotes();
    error NotAPool();
    error NotApprovedOrOwner();
    error NotGovernor();
    error NotEmergencyCouncil();
    error NotMinter();
    error NotWhitelistedNFT();
    error NotWhitelistedToken();
    error SameValue();
    error SpecialVotingWindow();
    error TooManyPools();
    error UnequalLengths();
    error ZeroBalance();
    error ZeroAddress();

    event GaugeCreated(
        address indexed poolFactory,
        address indexed votingRewardsFactory,
        address indexed gaugeFactory,
        address pool,
        address bribeVotingReward,
        address feeVotingReward,
        address gauge,
        address creator
    );
    event GaugeKilled(address indexed gauge);
    event GaugeRevived(address indexed gauge);
    event Voted(
        address indexed voter,
        address indexed pool,
        uint256 indexed tokenId,
        uint256 weight,
        uint256 totalWeight,
        uint256 timestamp
    );
    event Abstained(
        address indexed voter,
        address indexed pool,
        uint256 indexed tokenId,
        uint256 weight,
        uint256 totalWeight,
        uint256 timestamp
    );
    event NotifyReward(address indexed sender, address indexed reward, uint256 amount);
    event DistributeReward(address indexed sender, address indexed gauge, uint256 amount);
    event WhitelistToken(address indexed whitelister, address indexed token, bool indexed _bool);
    event WhitelistNFT(address indexed whitelister, uint256 indexed tokenId, bool indexed _bool);

    /// @notice Store trusted forwarder address to pass into factories
    function forwarder() external view returns (address);

    /// @notice The ve token that governs these contracts
    function ve() external view returns (address);

    /// @notice Factory registry for valid pool / gauge / rewards factories
    function factoryRegistry() external view returns (address);

    /// @notice Address of Minter.sol
    function minter() external view returns (address);

    /// @notice Standard OZ IGovernor using ve for vote weights.
    function governor() external view returns (address);

    /// @notice Custom Epoch Governor using ve for vote weights.
    function epochGovernor() external view returns (address);

    /// @notice credibly neutral party similar to Curve's Emergency DAO
    function emergencyCouncil() external view returns (address);

    /// @dev Total Voting Weights
    function totalWeight() external view returns (uint256);

    /// @dev Most number of pools one voter can vote for at once
    function maxVotingNum() external view returns (uint256);

    // mappings
    /// @dev Pool => Gauge
    function gauges(address pool) external view returns (address);

    /// @dev Gauge => Pool
    function poolForGauge(address gauge) external view returns (address);

    /// @dev Gauge => Fees Voting Reward
    function gaugeToFees(address gauge) external view returns (address);

    /// @dev Gauge => Bribes Voting Reward
    function gaugeToBribe(address gauge) external view returns (address);

    /// @dev Pool => Weights
    function weights(address pool) external view returns (uint256);

    /// @dev NFT => Pool => Votes
    function votes(uint256 tokenId, address pool) external view returns (uint256);

    /// @dev NFT => Total voting weight of NFT
    function usedWeights(uint256 tokenId) external view returns (uint256);

    /// @dev Nft => Timestamp of last vote (ensures single vote per epoch)
    function lastVoted(uint256 tokenId) external view returns (uint256);

    /// @dev Address => Gauge
    function isGauge(address) external view returns (bool);

    /// @dev Token => Whitelisted status
    function isWhitelistedToken(address token) external view returns (bool);

    /// @dev TokenId => Whitelisted status
    function isWhitelistedNFT(uint256 tokenId) external view returns (bool);

    /// @dev Gauge => Liveness status
    function isAlive(address gauge) external view returns (bool);

    /// @dev Gauge => Amount claimable
    function claimable(address gauge) external view returns (uint256);

    /// @notice Number of pools with a Gauge
    function length() external view returns (uint256);

    /// @notice Called by Minter to distribute weekly emissions rewards for disbursement amongst gauges.
    /// @dev Assumes totalWeight != 0 (Will never be zero as long as users are voting).
    ///      Throws if not called by minter.
    /// @param _amount Amount of rewards to distribute.
    function notifyRewardAmount(uint256 _amount) external;

    /// @dev Utility to distribute to gauges of pools in range _start to _finish.
    /// @param _start   Starting index of gauges to distribute to.
    /// @param _finish  Ending index of gauges to distribute to.
    function distribute(uint256 _start, uint256 _finish) external;

    /// @dev Utility to distribute to gauges of pools in array.
    /// @param _gauges Array of gauges to distribute to.
    function distribute(address[] memory _gauges) external;

    /// @notice Called by users to update voting balances in voting rewards contracts.
    /// @param _tokenId Id of veNFT whose balance you wish to update.
    function poke(uint256 _tokenId) external;

    /// @notice Called by users to vote for pools. Votes distributed proportionally based on weights.
    ///         Can only vote or deposit into a managed NFT once per epoch.
    ///         Can only vote for gauges that have not been killed.
    /// @dev Weights are distributed proportional to the sum of the weights in the array.
    ///      Throws if length of _poolVote and _weights do not match.
    /// @param _tokenId     Id of veNFT you are voting with.
    /// @param _poolVote    Array of pools you are voting for.
    /// @param _weights     Weights of pools.
    function vote(uint256 _tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external;

    /// @notice Called by users to reset voting state. Required if you wish to make changes to
    ///         veNFT state (e.g. merge, split, deposit into managed etc).
    ///         Cannot reset in the same epoch that you voted in.
    ///         Can vote or deposit into a managed NFT again after reset.
    /// @param _tokenId Id of veNFT you are reseting.
    function reset(uint256 _tokenId) external;

    /// @notice Called by users to deposit into a managed NFT.
    ///         Can only vote or deposit into a managed NFT once per epoch.
    ///         Note that NFTs deposited into a managed NFT will be re-locked
    ///         to the maximum lock time on withdrawal.
    /// @dev Throws if not approved or owner.
    ///      Throws if managed NFT is inactive.
    ///      Throws if depositing within privileged window (one hour prior to epoch flip).
    function depositManaged(uint256 _tokenId, uint256 _mTokenId) external;

    /// @notice Called by users to withdraw from a managed NFT.
    ///         Cannot do it in the same epoch that you deposited into a managed NFT.
    ///         Can vote or deposit into a managed NFT again after withdrawing.
    ///         Note that the NFT withdrawn is re-locked to the maximum lock time.
    function withdrawManaged(uint256 _tokenId) external;

    /// @notice Claim emissions from gauges.
    /// @param _gauges Array of gauges to collect emissions from.
    function claimRewards(address[] memory _gauges) external;

    /// @notice Claim bribes for a given NFT.
    /// @dev Utility to help batch bribe claims.
    /// @param _bribes  Array of BribeVotingReward contracts to collect from.
    /// @param _tokens  Array of tokens that are used as bribes.
    /// @param _tokenId Id of veNFT that you wish to claim bribes for.
    function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint256 _tokenId) external;

    /// @notice Claim fees for a given NFT.
    /// @dev Utility to help batch fee claims.
    /// @param _fees    Array of FeesVotingReward contracts to collect from.
    /// @param _tokens  Array of tokens that are used as fees.
    /// @param _tokenId Id of veNFT that you wish to claim fees for.
    function claimFees(address[] memory _fees, address[][] memory _tokens, uint256 _tokenId) external;

    /// @notice Set new governor.
    /// @dev Throws if not called by governor.
    /// @param _governor .
    function setGovernor(address _governor) external;

    /// @notice Set new epoch based governor.
    /// @dev Throws if not called by governor.
    /// @param _epochGovernor .
    function setEpochGovernor(address _epochGovernor) external;

    /// @notice Set new emergency council.
    /// @dev Throws if not called by emergency council.
    /// @param _emergencyCouncil .
    function setEmergencyCouncil(address _emergencyCouncil) external;

    /// @notice Set maximum number of gauges that can be voted for.
    /// @dev Throws if not called by governor.
    ///      Throws if _maxVotingNum is too low.
    ///      Throws if the values are the same.
    /// @param _maxVotingNum .
    function setMaxVotingNum(uint256 _maxVotingNum) external;

    /// @notice Whitelist (or unwhitelist) token for use in bribes.
    /// @dev Throws if not called by governor.
    /// @param _token .
    /// @param _bool .
    function whitelistToken(address _token, bool _bool) external;

    /// @notice Whitelist (or unwhitelist) token id for voting in last hour prior to epoch flip.
    /// @dev Throws if not called by governor.
    ///      Throws if already whitelisted.
    /// @param _tokenId .
    /// @param _bool .
    function whitelistNFT(uint256 _tokenId, bool _bool) external;

    /// @notice Create a new gauge (unpermissioned).
    /// @dev Governor can create a new gauge for a pool with any address.
    /// @param _poolFactory .
    /// @param _pool .
    function createGauge(address _poolFactory, address _pool) external returns (address);

    /// @notice Kills a gauge. The gauge will not receive any new emissions and cannot be deposited into.
    ///         Can still withdraw from gauge.
    /// @dev Throws if not called by emergency council.
    ///      Throws if gauge already killed.
    /// @param _gauge .
    function killGauge(address _gauge) external;

    /// @notice Revives a killed gauge. Gauge will can receive emissions and deposits again.
    /// @dev Throws if not called by emergency council.
    ///      Throws if gauge is not killed.
    /// @param _gauge .
    function reviveGauge(address _gauge) external;

    /// @dev Update claims to emissions for an array of gauges.
    /// @param _gauges Array of gauges to update emissions for.
    function updateFor(address[] memory _gauges) external;

    /// @dev Update claims to emissions for gauges based on their pool id as stored in Voter.
    /// @param _start   Starting index of pools.
    /// @param _end     Ending index of pools.
    function updateFor(uint256 _start, uint256 _end) external;

    /// @dev Update claims to emissions for single gauge
    /// @param _gauge .
    function updateFor(address _gauge) external;
}
pragma solidity ^0.8.0;

/// Modified IVotes interface for tokenId based voting
interface IVotes {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, uint256 indexed fromDelegate, uint256 indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the amount of votes that `tokenId` had at a specific moment in the past.
     *      If the account passed in is not the owner, returns 0.
     */
    function getPastVotes(address account, uint256 tokenId, uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value the end of the corresponding block.
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the delegate that `tokenId` has chosen. Can never be equal to the delegator's `tokenId`.
     *      Returns 0 if not delegated.
     */
    function delegates(uint256 tokenId) external view returns (uint256);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(uint256 delegator, uint256 delegatee) external;

    /**
     * @dev Delegates votes from `delegator` to `delegatee`. Signer must own `delegator`.
     */
    function delegateBySig(
        uint256 delegator,
        uint256 delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.8;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * _Available since v3.4._
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
 */
abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant _TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {EIP-5267}.
     */
    function eip712Domain()
        public
        view
        virtual
        override
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _name.toStringWithFallback(_nameFallback),
            _version.toStringWithFallback(_versionFallback),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }
}
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}
pragma solidity ^0.8.0;

interface IVotingEscrow is IVotes, IERC4906, IERC6372, IERC721Metadata {
    struct LockedBalance {
        int128 amount;
        uint256 end;
        bool isPermanent;
    }

    struct UserPoint {
        int128 bias;
        int128 slope; // # -dweight / dt
        uint256 ts;
        uint256 blk; // block
        uint256 permanent;
    }

    struct GlobalPoint {
        int128 bias;
        int128 slope; // # -dweight / dt
        uint256 ts;
        uint256 blk; // block
        uint256 permanentLockBalance;
    }

    /// @notice A checkpoint for recorded delegated voting weights at a certain timestamp
    struct Checkpoint {
        uint256 fromTimestamp;
        address owner;
        uint256 delegatedBalance;
        uint256 delegatee;
    }

    enum DepositType {
        DEPOSIT_FOR_TYPE,
        CREATE_LOCK_TYPE,
        INCREASE_LOCK_AMOUNT,
        INCREASE_UNLOCK_TIME
    }

    /// @dev Different types of veNFTs:
    /// NORMAL  - typical veNFT
    /// LOCKED  - veNFT which is locked into a MANAGED veNFT
    /// MANAGED - veNFT which can accept the deposit of NORMAL veNFTs
    enum EscrowType {
        NORMAL,
        LOCKED,
        MANAGED
    }

    error AlreadyVoted();
    error AmountTooBig();
    error ERC721ReceiverRejectedTokens();
    error ERC721TransferToNonERC721ReceiverImplementer();
    error InvalidNonce();
    error InvalidSignature();
    error InvalidSignatureS();
    error InvalidManagedNFTId();
    error LockDurationNotInFuture();
    error LockDurationTooLong();
    error LockExpired();
    error LockNotExpired();
    error NoLockFound();
    error NonExistentToken();
    error NotApprovedOrOwner();
    error NotDistributor();
    error NotEmergencyCouncilOrGovernor();
    error NotGovernor();
    error NotGovernorOrManager();
    error NotManagedNFT();
    error NotManagedOrNormalNFT();
    error NotLockedNFT();
    error NotNormalNFT();
    error NotPermanentLock();
    error NotOwner();
    error NotTeam();
    error NotVoter();
    error OwnershipChange();
    error PermanentLock();
    error SameAddress();
    error SameNFT();
    error SameState();
    error SplitNoOwner();
    error SplitNotAllowed();
    error SignatureExpired();
    error TooManyTokenIDs();
    error ZeroAddress();
    error ZeroAmount();
    error ZeroBalance();

    event Deposit(
        address indexed provider,
        uint256 indexed tokenId,
        DepositType indexed depositType,
        uint256 value,
        uint256 locktime,
        uint256 ts
    );
    event Withdraw(address indexed provider, uint256 indexed tokenId, uint256 value, uint256 ts);
    event LockPermanent(address indexed _owner, uint256 indexed _tokenId, uint256 amount, uint256 _ts);
    event UnlockPermanent(address indexed _owner, uint256 indexed _tokenId, uint256 amount, uint256 _ts);
    event Supply(uint256 prevSupply, uint256 supply);
    event Merge(
        address indexed _sender,
        uint256 indexed _from,
        uint256 indexed _to,
        uint256 _amountFrom,
        uint256 _amountTo,
        uint256 _amountFinal,
        uint256 _locktime,
        uint256 _ts
    );
    event Split(
        uint256 indexed _from,
        uint256 indexed _tokenId1,
        uint256 indexed _tokenId2,
        address _sender,
        uint256 _splitAmount1,
        uint256 _splitAmount2,
        uint256 _locktime,
        uint256 _ts
    );
    event CreateManaged(
        address indexed _to,
        uint256 indexed _mTokenId,
        address indexed _from,
        address _lockedManagedReward,
        address _freeManagedReward
    );
    event DepositManaged(
        address indexed _owner,
        uint256 indexed _tokenId,
        uint256 indexed _mTokenId,
        uint256 _weight,
        uint256 _ts
    );
    event WithdrawManaged(
        address indexed _owner,
        uint256 indexed _tokenId,
        uint256 indexed _mTokenId,
        uint256 _weight,
        uint256 _ts
    );
    event SetAllowedManager(address indexed _allowedManager);

    // State variables
    /// @notice Address of Meta-tx Forwarder
    function forwarder() external view returns (address);

    /// @notice Address of FactoryRegistry.sol
    function factoryRegistry() external view returns (address);

    /// @notice Address of token (HYDRO) used to create a veNFT
    function token() external view returns (address);

    /// @notice Address of RewardsDistributor.sol
    function distributor() external view returns (address);

    /// @notice Address of Voter.sol
    function voter() external view returns (address);

    /// @notice Address of Protocol Team multisig
    function team() external view returns (address);

    /// @notice Address of art proxy used for on-chain art generation
    function artProxy() external view returns (address);

    /// @dev address which can create managed NFTs
    function allowedManager() external view returns (address);

    /// @dev Current count of token
    function tokenId() external view returns (uint256);

    /*///////////////////////////////////////////////////////////////
                            MANAGED NFT STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @dev Mapping of token id to escrow type
    ///      Takes advantage of the fact default value is EscrowType.NORMAL
    function escrowType(uint256 tokenId) external view returns (EscrowType);

    /// @dev Mapping of token id to managed id
    function idToManaged(uint256 tokenId) external view returns (uint256 managedTokenId);

    /// @dev Mapping of user token id to managed token id to weight of token id
    function weights(uint256 tokenId, uint256 managedTokenId) external view returns (uint256 weight);

    /// @dev Mapping of managed id to deactivated state
    function deactivated(uint256 tokenId) external view returns (bool inactive);

    /// @dev Mapping from managed nft id to locked managed rewards
    ///      `token` denominated rewards (rebases/rewards) stored in locked managed rewards contract
    ///      to prevent co-mingling of assets
    function managedToLocked(uint256 tokenId) external view returns (address);

    /// @dev Mapping from managed nft id to free managed rewards contract
    ///      these rewards can be freely withdrawn by users
    function managedToFree(uint256 tokenId) external view returns (address);

    /*///////////////////////////////////////////////////////////////
                            MANAGED NFT LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Create managed NFT (a permanent lock) for use within ecosystem.
    /// @dev Throws if address already owns a managed NFT.
    /// @return _mTokenId managed token id.
    function createManagedLockFor(address _to) external returns (uint256 _mTokenId);

    /// @notice Delegates balance to managed nft
    ///         Note that NFTs deposited into a managed NFT will be re-locked
    ///         to the maximum lock time on withdrawal.
    ///         Permanent locks that are deposited will automatically unlock.
    /// @dev Managed nft will remain max-locked as long as there is at least one
    ///      deposit or withdrawal per week.
    ///      Throws if deposit nft is managed.
    ///      Throws if recipient nft is not managed.
    ///      Throws if deposit nft is already locked.
    ///      Throws if not called by voter.
    /// @param _tokenId tokenId of NFT being deposited
    /// @param _mTokenId tokenId of managed NFT that will receive the deposit
    function depositManaged(uint256 _tokenId, uint256 _mTokenId) external;

    /// @notice Retrieves locked rewards and withdraws balance from managed nft.
    ///         Note that the NFT withdrawn is re-locked to the maximum lock time.
    /// @dev Throws if NFT not locked.
    ///      Throws if not called by voter.
    /// @param _tokenId tokenId of NFT being deposited.
    function withdrawManaged(uint256 _tokenId) external;

    /// @notice Permit one address to call createManagedLockFor() that is not Voter.governor()
    function setAllowedManager(address _allowedManager) external;

    /// @notice Set Managed NFT state. Inactive NFTs cannot be deposited into.
    /// @param _mTokenId managed nft state to set
    /// @param _state true => inactive, false => active
    function setManagedState(uint256 _mTokenId, bool _state) external;

    /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function version() external view returns (string memory);

    function decimals() external view returns (uint8);

    function setTeam(address _team) external;

    function setArtProxy(address _proxy) external;

    /// @inheritdoc IERC721Metadata
    function tokenURI(uint256 tokenId) external view returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @dev Mapping from owner address to mapping of index to tokenId
    function ownerToNFTokenIdList(address _owner, uint256 _index) external view returns (uint256 _tokenId);

    /// @inheritdoc IERC721
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /// @inheritdoc IERC721
    function balanceOf(address owner) external view returns (uint256 balance);

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IERC721
    function getApproved(uint256 _tokenId) external view returns (address operator);

    /// @inheritdoc IERC721
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /// @notice Check whether spender is owner or an approved user for a given veNFT
    /// @param _spender .
    /// @param _tokenId .
    function isApprovedOrOwner(address _spender, uint256 _tokenId) external returns (bool);

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IERC721
    function approve(address to, uint256 tokenId) external;

    /// @inheritdoc IERC721
    function setApprovalForAll(address operator, bool approved) external;

    /// @inheritdoc IERC721
    function transferFrom(address from, address to, uint256 tokenId) external;

    /// @inheritdoc IERC721
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /// @inheritdoc IERC721
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 _interfaceID) external view returns (bool);

    /*//////////////////////////////////////////////////////////////
                             ESCROW STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice Total count of epochs witnessed since contract creation
    function epoch() external view returns (uint256);

    /// @notice Total amount of token() deposited
    function supply() external view returns (uint256);

    /// @notice Aggregate permanent locked balances
    function permanentLockBalance() external view returns (uint256);

    function userPointEpoch(uint256 _tokenId) external view returns (uint256 _epoch);

    /// @notice time -> signed slope change
    function slopeChanges(uint256 _timestamp) external view returns (int128);

    /// @notice account -> can split
    function canSplit(address _account) external view returns (bool);

    /// @notice Global point history at a given index
    function pointHistory(uint256 _loc) external view returns (GlobalPoint memory);

    /// @notice Get the LockedBalance (amount, end) of a _tokenId
    /// @param _tokenId .
    /// @return LockedBalance of _tokenId
    function locked(uint256 _tokenId) external view returns (LockedBalance memory);

    /// @notice User -> UserPoint[userEpoch]
    function userPointHistory(uint256 _tokenId, uint256 _loc) external view returns (UserPoint memory);

    /*//////////////////////////////////////////////////////////////
                              ESCROW LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Record global data to checkpoint
    function checkpoint() external;

    /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock
    /// @dev Anyone (even a smart contract) can deposit for someone else, but
    ///      cannot extend their locktime and deposit for a brand new user
    /// @param _tokenId lock NFT
    /// @param _value Amount to add to user's lock
    function depositFor(uint256 _tokenId, uint256 _value) external;

    /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lockDuration`
    /// @param _value Amount to deposit
    /// @param _lockDuration Number of seconds to lock tokens for (rounded down to nearest week)
    /// @return TokenId of created veNFT
    function createLock(uint256 _value, uint256 _lockDuration) external returns (uint256);

    /// @notice Deposit `_value` tokens for `_to` and lock for `_lockDuration`
    /// @param _value Amount to deposit
    /// @param _lockDuration Number of seconds to lock tokens for (rounded down to nearest week)
    /// @param _to Address to deposit
    /// @return TokenId of created veNFT
    function createLockFor(uint256 _value, uint256 _lockDuration, address _to) external returns (uint256);

    /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time
    /// @param _value Amount of tokens to deposit and add to the lock
    function increaseAmount(uint256 _tokenId, uint256 _value) external;

    /// @notice Extend the unlock time for `_tokenId`
    ///         Cannot extend lock time of permanent locks
    /// @param _lockDuration New number of seconds until tokens unlock
    function increaseUnlockTime(uint256 _tokenId, uint256 _lockDuration) external;

    /// @notice Withdraw all tokens for `_tokenId`
    /// @dev Only possible if the lock is both expired and not permanent
    ///      This will burn the veNFT. Any rebases or rewards that are unclaimed
    ///      will no longer be claimable. Claim all rebases and rewards prior to calling this.
    function withdraw(uint256 _tokenId) external;

    /// @notice Merges `_from` into `_to`.
    /// @dev Cannot merge `_from` locks that are permanent or have already voted this epoch.
    ///      Cannot merge `_to` locks that have already expired.
    ///      This will burn the veNFT. Any rebases or rewards that are unclaimed
    ///      will no longer be claimable. Claim all rebases and rewards prior to calling this.
    /// @param _from VeNFT to merge from.
    /// @param _to VeNFT to merge into.
    function merge(uint256 _from, uint256 _to) external;

    /// @notice Splits veNFT into two new veNFTS - one with oldLocked.amount - `_amount`, and the second with `_amount`
    /// @dev    This burns the tokenId of the target veNFT
    ///         Callable by approved or owner
    ///         If this is called by approved, approved will not have permissions to manipulate the newly created veNFTs
    ///         Returns the two new split veNFTs to owner
    ///         If `from` is permanent, will automatically dedelegate.
    ///         This will burn the veNFT. Any rebases or rewards that are unclaimed
    ///         will no longer be claimable. Claim all rebases and rewards prior to calling this.
    /// @param _from VeNFT to split.
    /// @param _amount Amount to split from veNFT.
    /// @return _tokenId1 Return tokenId of veNFT with oldLocked.amount - `_amount`.
    /// @return _tokenId2 Return tokenId of veNFT with `_amount`.
    function split(uint256 _from, uint256 _amount) external returns (uint256 _tokenId1, uint256 _tokenId2);

    /// @notice Toggle split for a specific address.
    /// @dev Toggle split for address(0) to enable or disable for all.
    /// @param _account Address to toggle split permissions
    /// @param _bool True to allow, false to disallow
    function toggleSplit(address _account, bool _bool) external;

    /// @notice Permanently lock a veNFT. Voting power will be equal to
    ///         `LockedBalance.amount` with no decay. Required to delegate.
    /// @dev Only callable by unlocked normal veNFTs.
    /// @param _tokenId tokenId to lock.
    function lockPermanent(uint256 _tokenId) external;

    /// @notice Unlock a permanently locked veNFT. Voting power will decay.
    ///         Will automatically dedelegate if delegated.
    /// @dev Only callable by permanently locked veNFTs.
    ///      Cannot unlock if already voted this epoch.
    /// @param _tokenId tokenId to unlock.
    function unlockPermanent(uint256 _tokenId) external;

    /*///////////////////////////////////////////////////////////////
                           GAUGE VOTING STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice Get the voting power for _tokenId at the current timestamp
    /// @dev Returns 0 if called in the same block as a transfer.
    /// @param _tokenId .
    /// @return Voting power
    function balanceOfNFT(uint256 _tokenId) external view returns (uint256);

    /// @notice Get the voting power for _tokenId at a given timestamp
    /// @param _tokenId .
    /// @param _t Timestamp to query voting power
    /// @return Voting power
    function balanceOfNFTAt(uint256 _tokenId, uint256 _t) external view returns (uint256);

    /// @notice Calculate total voting power at current timestamp
    /// @return Total voting power at current timestamp
    function totalSupply() external view returns (uint256);

    /// @notice Calculate total voting power at a given timestamp
    /// @param _t Timestamp to query total voting power
    /// @return Total voting power at given timestamp
    function totalSupplyAt(uint256 _t) external view returns (uint256);

    /*///////////////////////////////////////////////////////////////
                            GAUGE VOTING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice See if a queried _tokenId has actively voted
    /// @param _tokenId .
    /// @return True if voted, else false
    function voted(uint256 _tokenId) external view returns (bool);

    /// @notice Set the global state voter and distributor
    /// @dev This is only called once, at setup
    function setVoterAndDistributor(address _voter, address _distributor) external;

    /// @notice Set `voted` for _tokenId to true or false
    /// @dev Only callable by voter
    /// @param _tokenId .
    /// @param _voted .
    function voting(uint256 _tokenId, bool _voted) external;

    /*///////////////////////////////////////////////////////////////
                            DAO VOTING STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice The number of checkpoints for each tokenId
    function numCheckpoints(uint256 tokenId) external view returns (uint48);

    /// @notice A record of states for signing / validating signatures
    function nonces(address account) external view returns (uint256);

    /// @inheritdoc IVotes
    function delegates(uint256 delegator) external view returns (uint256);

    /// @notice A record of delegated token checkpoints for each account, by index
    /// @param tokenId .
    /// @param index .
    /// @return Checkpoint
    function checkpoints(uint256 tokenId, uint48 index) external view returns (Checkpoint memory);

    /// @inheritdoc IVotes
    function getPastVotes(address account, uint256 tokenId, uint256 timestamp) external view returns (uint256);

    /// @inheritdoc IVotes
    function getPastTotalSupply(uint256 timestamp) external view returns (uint256);

    /*///////////////////////////////////////////////////////////////
                             DAO VOTING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IVotes
    function delegate(uint256 delegator, uint256 delegatee) external;

    /// @inheritdoc IVotes
    function delegateBySig(
        uint256 delegator,
        uint256 delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /*//////////////////////////////////////////////////////////////
                              ERC6372 LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IERC6372
    function clock() external view returns (uint48);

    /// @inheritdoc IERC6372
    function CLOCK_MODE() external view returns (string memory);
}
pragma solidity ^0.8.0;

/**
 * @dev Taken from OpenZeppelin's IGovernor.
 *      Includes support for veto-ing as mitigation against a 51% attack.
 */
abstract contract IVetoGovernor is IERC165, IERC6372 {
    enum ProposalState {
        Pending,
        Active,
        Canceled,
        Defeated,
        Succeeded,
        Expired,
        Queued, // unused, required for backwards compatibility
        Executed,
        Vetoed
    }

    /**
     * @dev Emitted when a proposal is created.
     */
    event ProposalCreated(
        uint256 proposalId,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 voteStart,
        uint256 voteEnd,
        string description
    );

    /**
     * @dev Emitted when a proposal is canceled.
     */
    event ProposalCanceled(uint256 proposalId);

    /**
     * @dev Emitted when a proposal is vetoed.
     */
    event ProposalVetoed(uint256 proposalId);

    /**
     * @dev Emitted when a proposal is executed.
     */
    event ProposalExecuted(uint256 proposalId);

    /**
     * @dev Emitted when a comment is cast on a certain proposal.
     */
    event Comment(uint256 indexed proposalId, address indexed account, uint256 indexed tokenId, string comment);

    /**
     * @dev Emitted when a vote is cast without params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     */
    event VoteCast(
        address indexed voter,
        uint256 indexed tokenId,
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string reason
    );

    /**
     * @dev Emitted when a vote is cast with params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     * `params` are additional encoded parameters. Their interpepretation also depends on the voting module used.
     */
    event VoteCastWithParams(
        address indexed voter,
        uint256 indexed tokenId,
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string reason,
        bytes params
    );

    /**
     * @notice module:core
     * @dev Name of the governor instance (used in building the ERC712 domain separator).
     */
    function name() public view virtual returns (string memory);

    /**
     * @notice module:core
     * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
     */
    function version() public view virtual returns (string memory);

    /**
     * @notice module:core
     * @dev See {IERC6372}
     */
    function clock() public view virtual override returns (uint48);

    /**
     * @notice module:core
     * @dev See EIP-6372.
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() public view virtual override returns (string memory);

    /// @notice Numerator used to calculate minimum voting power required to comment.
    function commentWeighting() external view virtual returns (uint256);

    /// @notice Denominator used to calculate minimum voting power required to comment.
    function COMMENT_DENOMINATOR() external view virtual returns (uint256);

    /// @notice Contract whose total supply / voting power is being used.
    function escrow() external view virtual returns (IVotingEscrow);

    /**
     * @notice module:voting
     * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
     * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
     * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
     *
     * There are 2 standard keys: `support` and `quorum`.
     *
     * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
     * - `quorum=bravo` means that only For votes are counted towards quorum.
     * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
     *
     * If a counting module makes use of encoded `params`, it should  include this under a `params` key with a unique
     * name that describes the behavior. For example:
     *
     * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
     * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
     *
     * NOTE: The string can be decoded by the standard
     * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
     * JavaScript class.
     */
    // solhint-disable-next-line func-name-mixedcase
    function COUNTING_MODE() public view virtual returns (string memory);

    /**
     * @notice module:core
     * @dev Hashing function used to (re)build the proposal id from the proposal details..
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash,
        address proposer
    ) public pure virtual returns (uint256);

    /**
     * @notice module:core
     * @dev Current state of a proposal, following Compound's convention
     */
    function state(uint256 proposalId) public view virtual returns (ProposalState);

    /**
     * @notice module:core
     * @dev Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the
     * snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the
     * following block.
     */
    function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);

    /**
     * @notice module:core
     * @dev Timepoint at which votes close. If using block number, votes close at the end of this block, so it is
     * possible to cast a vote during this block.
     */
    function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay, between the proposal is created and the vote starts. The unit this duration is expressed in depends
     * on the clock (see EIP-6372) this contract uses.
     *
     * This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a
     * proposal starts.
     */
    function votingDelay() public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay, between the vote start and vote ends. The unit this duration is expressed in depends on the clock
     * (see EIP-6372) this contract uses.
     *
     * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
     * duration compared to the voting delay.
     */
    function votingPeriod() public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Minimum number of cast voted required for a proposal to be successful.
     *
     * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This allows to scale the
     * quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}).
     */
    function quorum(uint256 timepoint) public view virtual returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `tokenId` at a specific `timepoint`.
     *
     * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
     * multiple), {ERC20Votes} tokens.
     */
    function getVotes(address account, uint256 tokenId, uint256 timepoint) public view virtual returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `tokenId` at a specific `timepoint` given additional encoded parameters.
     */
    function getVotesWithParams(
        address account,
        uint256 tokenId,
        uint256 timepoint,
        bytes memory params
    ) public view virtual returns (uint256);

    /**
     * @notice module:voting
     * @dev Returns whether `tokenId` has cast a vote on `proposalId`.
     */
    function hasVoted(uint256 proposalId, uint256 tokenId) public view virtual returns (bool);

    /**
     * @dev Create a new proposal. Vote start after a delay specified by {IGovernor-votingDelay} and lasts for a
     * duration specified by {IGovernor-votingPeriod}.
     *
     * Emits a {ProposalCreated} event.
     */
    function propose(
        uint256 tokenId,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        string memory description
    ) public virtual returns (uint256 proposalId);

    /**
     * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
     * deadline to be reached.
     *
     * Emits a {ProposalExecuted} event.
     *
     * Note: some module can modify the requirements for execution, for example by adding an additional timelock.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash,
        address proposer
    ) public payable virtual returns (uint256 proposalId);

    /**
     * @dev Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e.
     * before the vote starts.
     *
     * Emits a {ProposalCanceled} event.
     */
    function cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public virtual returns (uint256 proposalId);

    /**
     * @dev Add a comment to a proposal
     *
     * Emits a {Comment} event.
     */
    function comment(uint256 proposalId, uint256 tokenId, string calldata message) external virtual;

    /**
     * @dev Cast a vote
     *
     * Emits a {VoteCast} event.
     */
    function castVote(uint256 proposalId, uint256 tokenId, uint8 support) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason
     *
     * Emits a {VoteCast} event.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        string calldata reason
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParams(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        string calldata reason,
        bytes memory params
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote using the user's cryptographic signature.
     *
     * Emits a {VoteCast} event.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParamsBySig(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        string calldata reason,
        bytes memory params,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual returns (uint256 balance);
}
// OpenZeppelin Contracts (last updated v4.8.0) (governance/Governor.sol)

pragma solidity ^0.8.0;
/**
 * @dev Modified lightly from OpenZeppelin's Governor contract to support vetoing.
 */
abstract contract VetoGovernor is Context, ERC165, EIP712, IVetoGovernor, IERC721Receiver, IERC1155Receiver {
    using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
    using SafeCast for uint256;

    bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
    bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
        keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)");

    // solhint-disable var-name-mixedcase
    struct ProposalCore {
        // --- start retyped from Timers.BlockNumber at offset 0x00 ---
        uint64 voteStart;
        address proposer;
        bytes4 __gap_unused0;
        // --- start retyped from Timers.BlockNumber at offset 0x20 ---
        uint64 voteEnd;
        bytes24 __gap_unused1;
        // --- Remaining fields starting at offset 0x40 ---------------
        bool executed;
        bool canceled;
        bool vetoed;
    }
    // solhint-enable var-name-mixedcase

    string private _name;
    uint256 public override commentWeighting = 0;
    uint256 public constant override COMMENT_DENOMINATOR = 1_000_000_000;
    IVotingEscrow public immutable override escrow;

    /// @custom:oz-retyped-from mapping(uint256 => Governor.ProposalCore)
    mapping(uint256 => ProposalCore) private _proposals;

    // This queue keeps track of the governor operating on itself. Calls to functions protected by the
    // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},
    // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the
    // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.
    DoubleEndedQueue.Bytes32Deque private _governanceCall;

    /**
     * @dev Restricts a function so it can only be executed through governance proposals. For example, governance
     * parameter setters in {GovernorSettings} are protected using this modifier.
     *
     * The governance executing address may be different from the Governor's own address, for example it could be a
     * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these
     * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,
     * for example, additional timelock proposers are not able to change governance parameters without going through the
     * governance protocol (since v4.6).
     */
    modifier onlyGovernance() {
        require(_msgSender() == _executor(), "Governor: onlyGovernance");
        if (_executor() != address(this)) {
            bytes32 msgDataHash = keccak256(_msgData());
            // loop until popping the expected operation - throw if deque is empty (operation not authorized)
            while (_governanceCall.popFront() != msgDataHash) {}
        }
        _;
    }

    /**
     * @dev Sets the value for {name} and {version}
     */
    constructor(string memory name_, IVotingEscrow _ve) EIP712(name_, version()) {
        _name = name_;
        escrow = _ve;
    }

    /**
     * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
     */
    receive() external payable virtual {
        require(_executor() == address(this));
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        // In addition to the current interfaceId, also support previous version of the interfaceId that did not
        // include the castVoteWithReasonAndParams() function as standard
        return
            interfaceId ==
            (type(IVetoGovernor).interfaceId ^
                type(IERC6372).interfaceId ^
                this.cancel.selector ^
                this.castVoteWithReasonAndParams.selector ^
                this.castVoteWithReasonAndParamsBySig.selector ^
                this.getVotesWithParams.selector) ||
            // Previous interface for backwards compatibility
            interfaceId == (type(IVetoGovernor).interfaceId ^ type(IERC6372).interfaceId ^ this.cancel.selector) ||
            interfaceId == type(IERC1155Receiver).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IVetoGovernor-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IVetoGovernor-version}.
     */
    function version() public view virtual override returns (string memory) {
        return "1";
    }

    /**
     * @dev See {IVetoGovernor-hashProposal}.
     *
     * The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array,
     * the descriptionHash (bytes32 which itself is the keccak256 hash of the description string) and the `proposer` address.
     * This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even
     * be computed in advance, before the proposal is submitted.
     *
     * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
     * same proposal (with same operation and same description) will have the same id if submitted on multiple governors
     * across multiple networks. This also means that in order to execute the same operation twice (on the same
     * governor) the proposer will have to change the description in order to avoid proposal id conflicts.
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash,
        address proposer
    ) public pure virtual override returns (uint256) {
        return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash, proposer)));
    }

    /**
     * @dev See {IVetoGovernor-state}.
     */
    function state(uint256 proposalId) public view virtual override returns (ProposalState) {
        ProposalCore storage proposal = _proposals[proposalId];

        if (proposal.executed) {
            return ProposalState.Executed;
        }

        if (proposal.canceled) {
            return ProposalState.Canceled;
        }

        if (proposal.vetoed) {
            return ProposalState.Vetoed;
        }

        uint256 snapshot = proposalSnapshot(proposalId);

        if (snapshot == 0) {
            revert("Governor: unknown proposal id");
        }

        uint256 currentTimepoint = clock();

        if (snapshot >= currentTimepoint) {
            return ProposalState.Pending;
        }

        uint256 deadline = proposalDeadline(proposalId);

        if (deadline >= currentTimepoint) {
            return ProposalState.Active;
        }

        if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {
            return ProposalState.Succeeded;
        } else {
            return ProposalState.Defeated;
        }
    }

    /**
     * @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
     */
    function proposalThreshold() public view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev See {IVetoGovernor-proposalSnapshot}.
     */
    function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
        return _proposals[proposalId].voteStart;
    }

    /**
     * @dev See {IVetoGovernor-proposalDeadline}.
     */
    function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
        return _proposals[proposalId].voteEnd;
    }

    /**
     * @dev Amount of votes already cast passes the threshold limit.
     */
    function _quorumReached(uint256 proposalId) internal view virtual returns (bool);

    /**
     * @dev Is the proposal successful or not.
     */
    function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);

    /**
     * @dev Get the voting weight of `tokenId`, owned by `account` at a specific `timepoint`, for a vote as described by `params`.
     */
    function _getVotes(
        address account,
        uint256 tokenId,
        uint256 timepoint,
        bytes memory params
    ) internal view virtual returns (uint256);

    /**
     * @dev Register a vote for `proposalId` by `tokenId` with a given `support`, voting `weight` and voting `params`.
     *
     * Note: Support is generic and can represent various things depending on the voting system used.
     */
    function _countVote(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        uint256 weight,
        bytes memory params
    ) internal virtual;

    /**
     * @dev Default additional encoded parameters used by castVote methods that don't include them
     *
     * Note: Should be overridden by specific implementations to use an appropriate value, the
     * meaning of the additional params, in the context of that implementation
     */
    function _defaultParams() internal view virtual returns (bytes memory) {
        return "";
    }

    /**
     * @dev See {IVetoGovernor-propose}.
     */
    function propose(
        uint256 tokenId,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        string memory description
    ) public virtual override returns (uint256) {
        address proposer = _msgSender();
        uint256 currentTimepoint = clock();

        require(
            getVotes(proposer, tokenId, currentTimepoint - 1) >= proposalThreshold(),
            "Governor: proposer votes below proposal threshold"
        );

        uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)), proposer);

        require(targets.length == values.length, "Governor: invalid proposal length");
        require(targets.length == calldatas.length, "Governor: invalid proposal length");
        require(targets.length > 0, "Governor: empty proposal");
        require(_proposals[proposalId].proposer == address(0), "Governor: proposal already exists");

        uint256 snapshot = currentTimepoint + votingDelay();
        uint256 deadline = snapshot + votingPeriod();

        _proposals[proposalId] = ProposalCore({
            voteStart: snapshot.toUint64(),
            proposer: proposer,
            __gap_unused0: 0,
            voteEnd: deadline.toUint64(),
            __gap_unused1: 0,
            executed: false,
            canceled: false,
            vetoed: false
        });

        emit ProposalCreated(
            proposalId,
            proposer,
            targets,
            values,
            new string[](targets.length),
            calldatas,
            snapshot,
            deadline,
            description
        );

        return proposalId;
    }

    /**
     * @dev See {IVetoGovernor-execute}.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash,
        address proposer
    ) public payable virtual override returns (uint256) {
        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash, proposer);

        ProposalState status = state(proposalId);
        require(status == ProposalState.Succeeded, "Governor: proposal not successful");
        _proposals[proposalId].executed = true;

        emit ProposalExecuted(proposalId);

        _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);
        _execute(proposalId, targets, values, calldatas, descriptionHash);
        _afterExecute(proposalId, targets, values, calldatas, descriptionHash);

        return proposalId;
    }

    /**
     * @dev See {IVetoGovernor-cancel}.
     */
    function cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public virtual override returns (uint256) {
        address proposer = _msgSender();
        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash, proposer);
        require(state(proposalId) == ProposalState.Pending, "Governor: too late to cancel");
        require(proposer == _proposals[proposalId].proposer, "Governor: only proposer can cancel");
        return _cancel(targets, values, calldatas, descriptionHash, proposer);
    }

    /**
     * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism
     */
    function _execute(
        uint256 /* proposalId */,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 /*descriptionHash*/
    ) internal virtual {
        string memory errorMessage = "Governor: call reverted without message";
        uint256 _length = targets.length;
        for (uint256 i = 0; i < _length; ++i) {
            (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
            Address.verifyCallResult(success, returndata, errorMessage);
        }
    }

    /**
     * @dev Hook before execution is triggered.
     */
    function _beforeExecute(
        uint256 /* proposalId */,
        address[] memory targets,
        uint256[] memory /* values */,
        bytes[] memory calldatas,
        bytes32 /*descriptionHash*/
    ) internal virtual {
        if (_executor() != address(this)) {
            uint256 _length = targets.length;
            for (uint256 i = 0; i < _length; ++i) {
                if (targets[i] == address(this)) {
                    _governanceCall.pushBack(keccak256(calldatas[i]));
                }
            }
        }
    }

    /**
     * @dev Hook after execution is triggered.
     */
    function _afterExecute(
        uint256 /* proposalId */,
        address[] memory /* targets */,
        uint256[] memory /* values */,
        bytes[] memory /* calldatas */,
        bytes32 /*descriptionHash*/
    ) internal virtual {
        if (_executor() != address(this)) {
            if (!_governanceCall.empty()) {
                _governanceCall.clear();
            }
        }
    }

    /**
     * @dev Internal veto mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
     * vetoed to allow distinguishing it from executed and canceled proposals.
     *
     * Emits a {IVetoGovernor-ProposalVetoed} event.
     */
    function _veto(uint256 proposalId) internal returns (uint256) {
        ProposalState status = state(proposalId);

        require(
            status != ProposalState.Vetoed &&
                status != ProposalState.Canceled &&
                status != ProposalState.Expired &&
                status != ProposalState.Executed,
            "Governor: proposal not active"
        );
        _proposals[proposalId].vetoed = true;

        emit ProposalVetoed(proposalId);

        return proposalId;
    }

    /**
     * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
     * canceled to allow distinguishing it from executed and canceled proposals.
     *
     * Emits a {IVetoGovernor-ProposalCanceled} event.
     */
    function _cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash,
        address proposer
    ) internal virtual returns (uint256) {
        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash, proposer);

        ProposalState status = state(proposalId);

        require(
            status != ProposalState.Vetoed &&
                status != ProposalState.Canceled &&
                status != ProposalState.Expired &&
                status != ProposalState.Executed,
            "Governor: proposal not active"
        );
        _proposals[proposalId].canceled = true;

        emit ProposalCanceled(proposalId);

        return proposalId;
    }

    /**
     * @dev See {IVetoGovernor-getVotes}.
     */
    function getVotes(
        address account,
        uint256 tokenId,
        uint256 timepoint
    ) public view virtual override returns (uint256) {
        return _getVotes(account, tokenId, timepoint, _defaultParams());
    }

    /**
     * @dev See {IVetoGovernor-getVotesWithParams}.
     */
    function getVotesWithParams(
        address account,
        uint256 tokenId,
        uint256 timepoint,
        bytes memory params
    ) public view virtual override returns (uint256) {
        return _getVotes(account, tokenId, timepoint, params);
    }

    /**
     * @dev See {IVetoGovernor-castVote}.
     */
    function castVote(uint256 proposalId, uint256 tokenId, uint8 support) public virtual override returns (uint256) {
        address voter = _msgSender();
        return _castVote(proposalId, voter, tokenId, support, "");
    }

    /**
     * @dev See {IVetoGovernor-castVoteWithReason}.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        string calldata reason
    ) public virtual override returns (uint256) {
        address voter = _msgSender();
        return _castVote(proposalId, voter, tokenId, support, reason);
    }

    /**
     * @dev See {IVetoGovernor-castVoteWithReasonAndParams}.
     */
    function castVoteWithReasonAndParams(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        string calldata reason,
        bytes memory params
    ) public virtual override returns (uint256) {
        address voter = _msgSender();
        return _castVote(proposalId, voter, tokenId, support, reason, params);
    }

    /**
     * @dev See {IVetoGovernor-castVoteBySig}.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override returns (uint256) {
        address voter = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
            v,
            r,
            s
        );
        return _castVote(proposalId, voter, tokenId, support, "");
    }

    /**
     * @dev See {IVetoGovernor-castVoteWithReasonAndParamsBySig}.
     */
    function castVoteWithReasonAndParamsBySig(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        string calldata reason,
        bytes memory params,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override returns (uint256) {
        address voter = ECDSA.recover(
            _hashTypedDataV4(
                keccak256(
                    abi.encode(
                        EXTENDED_BALLOT_TYPEHASH,
                        proposalId,
                        support,
                        keccak256(bytes(reason)),
                        keccak256(params)
                    )
                )
            ),
            v,
            r,
            s
        );

        return _castVote(proposalId, voter, tokenId, support, reason, params);
    }

    /**
     * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
     * voting weight using {IVetoGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
     *
     * Emits a {IVetoGovernor-VoteCast} event.
     */
    function _castVote(
        uint256 proposalId,
        address account,
        uint256 tokenId,
        uint8 support,
        string memory reason
    ) internal virtual returns (uint256) {
        return _castVote(proposalId, account, tokenId, support, reason, _defaultParams());
    }

    /**
     * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
     * voting weight using {IVetoGovernor-getVotes} and call the {_countVote} internal function.
     *
     * Emits a {IVetoGovernor-VoteCast} event.
     */
    function _castVote(
        uint256 proposalId,
        address account,
        uint256 tokenId,
        uint8 support,
        string memory reason,
        bytes memory params
    ) internal virtual returns (uint256) {
        ProposalCore storage proposal = _proposals[proposalId];
        require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");

        uint256 weight = _getVotes(account, tokenId, proposal.voteStart, params);
        _countVote(proposalId, tokenId, support, weight, params);

        if (params.length == 0) {
            emit VoteCast(account, tokenId, proposalId, support, weight, reason);
        } else {
            emit VoteCastWithParams(account, tokenId, proposalId, support, weight, reason, params);
        }

        return weight;
    }

    /**
     * @dev Comment mechanism for active or pending proposals. Requires a certain amount of votes. Emits a comment
     *      containing the message.
     *
     * Emits a {IVetoGovernor-Comment} event.
     */
    function comment(uint256 proposalId, uint256 tokenId, string calldata message) external virtual override {
        bytes memory params;
        ProposalCore storage proposal = _proposals[proposalId];
        ProposalState status = state(proposalId);
        require(status == ProposalState.Active || status == ProposalState.Pending, "Governor: not active or pending");
        uint256 startTime = proposal.voteStart;
        address account = _msgSender();
        uint256 weight = _getVotes(account, tokenId, startTime, params);
        uint256 minimumWeight = (escrow.getPastTotalSupply(startTime) * commentWeighting) / 10_000;
        require(weight > minimumWeight, "Governor: insufficient voting power");

        emit Comment(proposalId, account, tokenId, message);
    }

    /**
     * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor
     * is some contract other than the governor itself, like when using a timelock, this function can be invoked
     * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.
     * Note that if the executor is simply the governor itself, use of `relay` is redundant.
     */
    function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance {
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        Address.verifyCallResult(success, returndata, "Governor: relay reverted without message");
    }

    /**
     * @dev Address through which the governor executes action. Will be overloaded by module that execute actions
     * through another contract such as a timelock.
     */
    function _executor() internal view virtual returns (address) {
        return address(this);
    }

    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     */
    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155Received}.
     */
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
     */
    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}
// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorCountingSimple.sol)

pragma solidity ^0.8.0;

/**
 * @dev OpenZeppelin's GovernorCountingSimple using VetoGovernor
 */
abstract contract VetoGovernorCountingSimple is VetoGovernor {
    /**
     * @dev Supported vote types. Matches Governor Bravo ordering.
     */
    enum VoteType {
        Against,
        For,
        Abstain
    }

    struct ProposalVote {
        uint256 againstVotes;
        uint256 forVotes;
        uint256 abstainVotes;
        mapping(uint256 => bool) hasVoted;
    }

    mapping(uint256 => ProposalVote) private _proposalVotes;

    /**
     * @dev See {IGovernor-COUNTING_MODE}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function COUNTING_MODE() public pure virtual override returns (string memory) {
        return "support=bravo&quorum=for,abstain";
    }

    /**
     * @dev See {IGovernor-hasVoted}.
     */
    function hasVoted(uint256 proposalId, uint256 tokenId) public view virtual override returns (bool) {
        return _proposalVotes[proposalId].hasVoted[tokenId];
    }

    /**
     * @dev Accessor to the internal vote counts.
     */
    function proposalVotes(
        uint256 proposalId
    ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];
        return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
    }

    /**
     * @dev See {Governor-_quorumReached}.
     */
    function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];

        return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;
    }

    /**
     * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
     */
    function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];

        return proposalVote.forVotes > proposalVote.againstVotes;
    }

    /**
     * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
     */
    function _countVote(
        uint256 proposalId,
        uint256 tokenId,
        uint8 support,
        uint256 weight,
        bytes memory // params
    ) internal virtual override {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];

        require(!proposalVote.hasVoted[tokenId], "GovernorVotingSimple: vote already cast");
        require(weight > 0, "GovernorVotingSimple: zero voting weight");
        proposalVote.hasVoted[tokenId] = true;

        if (support == uint8(VoteType.Against)) {
            proposalVote.againstVotes += weight;
        } else if (support == uint8(VoteType.For)) {
            proposalVote.forVotes += weight;
        } else if (support == uint8(VoteType.Abstain)) {
            proposalVote.abstainVotes += weight;
        } else {
            revert("GovernorVotingSimple: invalid value for enum VoteType");
        }
    }
}
pragma solidity 0.8.19;

library DelegationHelperLibrary {
    uint256 public constant DURATION = 7 days;

    /// Helper function to fetch the checkpoint for the last voting checkpoint prior to a timepoint
    /// Adapted from DelegationLogicLibrary.sol:getPastVotesIndex(uint256 tokenId, uint256 timestamp)
    function getPastCheckpointIndex(
        IVotingEscrow ve,
        uint256 mTokenId,
        uint256 timepoint
    ) internal view returns (uint48) {
        uint48 nCheckpoints = ve.numCheckpoints(mTokenId);
        if (nCheckpoints == 0) return 0;
        // First check most recent balance
        if (ve.checkpoints(mTokenId, nCheckpoints - 1).fromTimestamp <= timepoint) return (nCheckpoints - 1);
        // Next check implicit zero balance
        if (ve.checkpoints(mTokenId, 0).fromTimestamp > timepoint) return 0;

        uint48 lower = 0;
        uint48 upper = nCheckpoints - 1;
        IVotingEscrow.Checkpoint memory cp;
        while (upper > lower) {
            uint48 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
            cp = ve.checkpoints(mTokenId, center);
            if (cp.fromTimestamp == timepoint) {
                return center;
            } else if (cp.fromTimestamp < timepoint) {
                lower = center;
            } else {
                upper = center - 1;
            }
        }
        return lower;
    }

    /// Helper function to calculate the locked balance owed to a locked nft at a certain timepoint
    /// It calculates the rewards until the end of the current epoch. As rewards are lagged by one epoch
    /// This means it includes rewards that the user is projected to get in the following epoch.
    /// These rewards are not immediately claimable, but the user can vote as if they claimed it.
    /// Adapted from Reward.sol:earned(address token, uint256 tokenId)
    function earned(
        IVotingEscrow ve,
        uint256 mTokenId,
        uint256 tokenId,
        uint256 timepoint
    ) internal view returns (uint256) {
        IReward lmr = IReward(ve.managedToLocked(mTokenId));
        if (lmr.numCheckpoints(tokenId) == 0) {
            return 0;
        }

        address _rewardToken = ve.token();
        uint256 reward = 0;
        uint256 _supply = 1;
        uint256 _currTs = ProtocolTimeLibrary.epochStart(lmr.lastEarn(_rewardToken, tokenId)); // take epoch last claimed in as starting point
        uint256 _index = lmr.getPriorBalanceIndex(tokenId, _currTs);
        (uint256 _cpTs, uint256 _cpBalanceOf) = lmr.checkpoints(tokenId, _index);

        // accounts for case where lastEarn is before first checkpoint
        _currTs = Math.max(_currTs, ProtocolTimeLibrary.epochStart(_cpTs));

        // get epochs between end of the current epoch and first checkpoint in same epoch as last claim
        uint256 numEpochs = (ProtocolTimeLibrary.epochNext(timepoint) - _currTs) / DURATION;
        uint256 _priorSupply;

        if (numEpochs > 0) {
            for (uint256 i = 0; i < numEpochs; i++) {
                // get index of last checkpoint in this epoch
                _index = lmr.getPriorBalanceIndex(tokenId, _currTs + DURATION - 1);
                // get checkpoint in this epoch
                (_cpTs, _cpBalanceOf) = lmr.checkpoints(tokenId, _index);
                // get supply of last checkpoint in this epoch
                (, _priorSupply) = lmr.supplyCheckpoints(lmr.getPriorSupplyIndex(_currTs + DURATION - 1));
                _supply = Math.max(_priorSupply, 1);
                reward += (_cpBalanceOf * lmr.tokenRewardsPerEpoch(_rewardToken, _currTs)) / _supply;
                _currTs += DURATION;
            }
        }

        return reward;
    }
}
// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)

pragma solidity ^0.8.0;

/**
 * @dev OpenZeppelin's GovernorVotes using VetoGovernor
 */
abstract contract VetoGovernorVotes is VetoGovernor {
    using DelegationHelperLibrary for IVotingEscrow;

    IVotes public immutable token;
    IVotingEscrow public immutable ve;

    constructor(IVotes votes) {
        token = votes;
        ve = IVotingEscrow(address(votes));
    }

    /**
     * @dev Clock (as specified in EIP-6372) is set to match the token's clock. Fallback to block numbers if the token
     * does not implement EIP-6372.
     */
    function clock() public view virtual override returns (uint48) {
        try IERC6372(address(token)).clock() returns (uint48 timepoint) {
            return timepoint;
        } catch {
            return SafeCast.toUint48(block.number);
        }
    }

    /**
     * @dev Machine-readable description of the clock as specified in EIP-6372.
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() public view virtual override returns (string memory) {
        try IERC6372(address(token)).CLOCK_MODE() returns (string memory clockmode) {
            return clockmode;
        } catch {
            return "mode=blocknumber&from=default";
        }
    }

    /**
     * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).
     */
    function _getVotes(
        address account,
        uint256 tokenId,
        uint256 timepoint,
        bytes memory /*params*/
    ) internal view virtual override returns (uint256) {
        IVotingEscrow.EscrowType escrowType = ve.escrowType(tokenId);
        require(escrowType != IVotingEscrow.EscrowType.MANAGED, "Governor: managed nft cannot vote");

        if (escrowType == IVotingEscrow.EscrowType.NORMAL) {
            return token.getPastVotes(account, tokenId, timepoint);
        }

        // only allow locked veNFT voting if underlying nft not delegating at timepoint
        uint256 mTokenId = ve.idToManaged(tokenId);
        uint48 index = ve.getPastCheckpointIndex(mTokenId, timepoint);
        uint256 delegatee = ve.checkpoints(mTokenId, index).delegatee;
        if (delegatee == 0) {
            // if mveNFT not delegating, voting balance = delegated balance +
            // initial contribution to mveNFT + accrued locked rewards
            uint256 delegatedBalance = token.getPastVotes(account, tokenId, timepoint);
            uint256 weight = ve.weights(tokenId, mTokenId); // initial deposit weight
            uint256 _earned = ve.earned(mTokenId, tokenId, timepoint); // accrued rewards
            return weight + _earned + delegatedBalance;
        }

        // nft locked and underlying nft delegating
        // balance will only be delegated balance
        return token.getPastVotes(account, tokenId, timepoint);
    }

    function getVotes(uint256 tokenId, uint256 timepoint) external view returns (uint256) {
        address account = ve.ownerOf(tokenId);
        return _getVotes(account, tokenId, timepoint, "");
    }
}
// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorVotesQuorumFraction.sol)

pragma solidity ^0.8.0;

/**
 * @dev OpenZeppelin's GovernorVotesQuorumFraction using VetoGovernor
 */
abstract contract VetoGovernorVotesQuorumFraction is VetoGovernorVotes {
    using SafeCast for *;
    using Checkpoints for Checkpoints.Trace224;

    uint256 private _quorumNumerator; // DEPRECATED in favor of _quorumNumeratorHistory

    /// @custom:oz-retyped-from Checkpoints.History
    Checkpoints.Trace224 private _quorumNumeratorHistory;

    event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);

    /**
     * @dev Initialize quorum as a fraction of the token's total supply.
     *
     * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is
     * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be
     * customized by overriding {quorumDenominator}.
     */
    constructor(uint256 quorumNumeratorValue) {
        _updateQuorumNumerator(quorumNumeratorValue);
    }

    /**
     * @dev Returns the current quorum numerator. See {quorumDenominator}.
     */
    function quorumNumerator() public view virtual returns (uint256) {
        return _quorumNumeratorHistory._checkpoints.length == 0 ? _quorumNumerator : _quorumNumeratorHistory.latest();
    }

    /**
     * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}.
     */
    function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
        // If history is empty, fallback to old storage
        uint256 length = _quorumNumeratorHistory._checkpoints.length;
        if (length == 0) {
            return _quorumNumerator;
        }

        // Optimistic search, check the latest checkpoint
        Checkpoints.Checkpoint224 memory latest = _quorumNumeratorHistory._checkpoints[length - 1];
        if (latest._key <= timepoint) {
            return latest._value;
        }

        // Otherwise, do the binary search
        return _quorumNumeratorHistory.upperLookupRecent(timepoint.toUint32());
    }

    /**
     * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.
     */
    function quorumDenominator() public view virtual returns (uint256) {
        return 100;
    }

    /**
     * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`.
     */
    function quorum(uint256 timepoint) public view virtual override returns (uint256) {
        return (token.getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator();
    }

    /**
     * @dev Changes the quorum numerator.
     *
     * Emits a {QuorumNumeratorUpdated} event.
     *
     * Requirements:
     *
     * - Must be called through a governance proposal.
     * - New numerator must be smaller or equal to the denominator.
     */
    function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {
        _updateQuorumNumerator(newQuorumNumerator);
    }

    /**
     * @dev Changes the quorum numerator.
     *
     * Emits a {QuorumNumeratorUpdated} event.
     *
     * Requirements:
     *
     * - New numerator must be smaller or equal to the denominator.
     */
    function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {
        require(
            newQuorumNumerator <= quorumDenominator(),
            "GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator"
        );

        uint256 oldQuorumNumerator = quorumNumerator();

        // Make sure we keep track of the original numerator in contracts upgraded from a version without checkpoints.
        if (oldQuorumNumerator != 0 && _quorumNumeratorHistory._checkpoints.length == 0) {
            _quorumNumeratorHistory._checkpoints.push(
                Checkpoints.Checkpoint224({_key: 0, _value: oldQuorumNumerator.toUint224()})
            );
        }

        // Set new quorum for future proposals
        _quorumNumeratorHistory.push(clock().toUint32(), newQuorumNumerator.toUint224());

        emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
    }
}
pragma solidity 0.8.19;

/// @title ProtocolGovernor
/// @author velodrome.finance, @figs999, @pegahcarter
/// @notice Protocol governance with timestamp-based voting power from VotingEscrow NFTs
///         Supports vetoing of proposals as mitigation for 51% attacks
///         Votes are cast and counted on a per tokenId basis
contract ProtocolGovernor is
    VetoGovernor,
    VetoGovernorCountingSimple,
    VetoGovernorVotes,
    VetoGovernorVotesQuorumFraction
{
    IVoter public immutable voter;
    address public team;
    address public pendingTeam;
    address public vetoer;
    address public pendingVetoer;
    uint256 public constant MAX_PROPOSAL_NUMERATOR = 500; // max 5%
    uint256 public constant PROPOSAL_DENOMINATOR = 10_000;
    uint256 public proposalNumerator = 0; // 1%

    error CommentWeightingTooHigh();
    error NotGovernor();
    error NotPendingTeam();
    error NotTeam();
    error NotPendingVetoer();
    error NotVetoer();
    error ProposalNumeratorTooHigh();
    error ZeroAddress();

    event AcceptTeam(address indexed newTeam);
    event AcceptVetoer(address indexed vetoer);
    event RenounceVetoer();
    event SetCommentWeighting(uint256 commentWeighting);
    event SetProposalNumerator(uint256 indexed proposalNumerator);

    constructor(
        IVotes _ve,
        IVoter _voter
    )
        VetoGovernor("Hydrometer Governor", IVotingEscrow(address(_ve)))
        VetoGovernorVotes(_ve)
        VetoGovernorVotesQuorumFraction(25)
    {
        vetoer = msg.sender;
        team = msg.sender;
        voter = _voter;
    }

    function votingDelay() public pure override(IVetoGovernor) returns (uint256) {
        return (2 days);
    }

    function votingPeriod() public pure override(IVetoGovernor) returns (uint256) {
        return (5 days);
    }

    function setProposalNumerator(uint256 numerator) external {
        if (msg.sender != team) revert NotTeam();
        if (numerator > MAX_PROPOSAL_NUMERATOR) revert ProposalNumeratorTooHigh();
        proposalNumerator = numerator;
        emit SetProposalNumerator(numerator);
    }

    function proposalThreshold() public view override(VetoGovernor) returns (uint256) {
        return (token.getPastTotalSupply(block.timestamp - 1) * proposalNumerator) / PROPOSAL_DENOMINATOR;
    }

    function setTeam(address _pendingTeam) external {
        if (_pendingTeam == address(0)) revert ZeroAddress();
        if (msg.sender != team) revert NotTeam();
        pendingTeam = _pendingTeam;
    }

    function acceptTeam() external {
        if (msg.sender != pendingTeam) revert NotPendingTeam();
        team = pendingTeam;
        delete pendingTeam;
        emit AcceptTeam(team);
    }

    /// @dev Vetoer can be removed once the risk of a 51% attack becomes unfeasible.
    ///      This can be done by transferring ownership of vetoer to a contract that is "bricked"
    ///      i.e. a non-zero address contract that is immutable with no ability to call this function.
    function setVetoer(address _vetoer) external {
        if (msg.sender != vetoer) revert NotVetoer();
        if (_vetoer == address(0)) revert ZeroAddress();
        pendingVetoer = _vetoer;
    }

    function acceptVetoer() external {
        if (msg.sender != pendingVetoer) revert NotPendingVetoer();
        vetoer = pendingVetoer;
        delete pendingVetoer;
        emit AcceptVetoer(vetoer);
    }

    /// @notice Support for vetoer to protect against 51% attacks
    function veto(uint256 _proposalId) external {
        if (msg.sender != vetoer) revert NotVetoer();
        _veto(_proposalId);
    }

    function renounceVetoer() external {
        if (msg.sender != vetoer) revert NotVetoer();
        delete vetoer;
        emit RenounceVetoer();
    }

    /// @notice Set minimum % of total supply required to comment
    /// @dev Callable only by voter.governor() (i.e. this contract)
    /// @param _commentWeighting Weighting required for comment (note the denominator value).
    function setCommentWeighting(uint256 _commentWeighting) external {
        if (_commentWeighting > COMMENT_DENOMINATOR) revert CommentWeightingTooHigh();
        if (msg.sender != voter.governor()) revert NotGovernor();
        commentWeighting = _commentWeighting;

        emit SetCommentWeighting(_commentWeighting);
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IVotes","name":"_ve","type":"address"},{"internalType":"contract IVoter","name":"_voter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CommentWeightingTooHigh","type":"error"},{"inputs":[],"name":"Empty","type":"error"},{"inputs":[],"name":"NotGovernor","type":"error"},{"inputs":[],"name":"NotPendingTeam","type":"error"},{"inputs":[],"name":"NotPendingVetoer","type":"error"},{"inputs":[],"name":"NotTeam","type":"error"},{"inputs":[],"name":"NotVetoer","type":"error"},{"inputs":[],"name":"ProposalNumeratorTooHigh","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newTeam","type":"address"}],"name":"AcceptTeam","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vetoer","type":"address"}],"name":"AcceptVetoer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"comment","type":"string"}],"name":"Comment","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"voteStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"voteEnd","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalVetoed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldQuorumNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorumNumerator","type":"uint256"}],"name":"QuorumNumeratorUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"RenounceVetoer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"commentWeighting","type":"uint256"}],"name":"SetCommentWeighting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalNumerator","type":"uint256"}],"name":"SetProposalNumerator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"}],"name":"VoteCastWithParams","type":"event"},{"inputs":[],"name":"BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMMENT_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COUNTING_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"EXTENDED_BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PROPOSAL_NUMERATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSAL_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"cancel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"castVoteWithReasonAndParams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteWithReasonAndParamsBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"message","type":"string"}],"name":"comment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commentWeighting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"escrow","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"},{"internalType":"address","name":"proposer","type":"address"}],"name":"execute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timepoint","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"getVotesWithParams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"hasVoted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"},{"internalType":"address","name":"proposer","type":"address"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingTeam","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingVetoer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalVotes","outputs":[{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"quorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"quorumNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_commentWeighting","type":"uint256"}],"name":"setCommentWeighting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"}],"name":"setProposalNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingTeam","type":"address"}],"name":"setTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vetoer","type":"address"}],"name":"setVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum IVetoGovernor.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"team","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IVotes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newQuorumNumerator","type":"uint256"}],"name":"updateQuorumNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_proposalId","type":"uint256"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vetoer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"contract IVoter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101e060405260006003556000600e553480156200001c57600080fd5b50604051620062b0380380620062b08339810160408190526200003f91620007e2565b6019826040518060400160405280601381526020017f487964726f6d6574657220476f7665726e6f720000000000000000000000000081525084816200008a620001af60201b60201c565b62000097826000620001ca565b60e052620000a7816001620001ca565b61010052815160208084019190912061012052815190820120610140524660a052620001376101205161014051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c05260026200014e8382620008c6565b506001600160a01b0390811661016052919091166101808190526101a05250620001788162000203565b50600c8054336001600160a01b03199182168117909255600a805490911690911790556001600160a01b03166101c0525062000a53565b6040805180820190915260018152603160f81b602082015290565b6000602083511015620001ea57620001e28362000386565b9050620001fd565b81620001f78482620008c6565b50600090505b92915050565b60648111156200028c5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4015b60405180910390fd5b600062000298620003c9565b90508015801590620002aa5750600954155b156200031257604080518082019091526000815260099060208101620002d084620003f8565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b62000347620003326200032462000467565b65ffffffffffff16620004de565b6200033d84620003f8565b6009919062000545565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b600080829050601f81511115620003b4578260405163305a27a960e01b815260040162000283919062000992565b8051620003c182620009e2565b179392505050565b60095460009015620003ef57620003e1600962000562565b6001600160e01b0316905090565b6008545b905090565b60006001600160e01b03821115620004635760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b606482015260840162000283565b5090565b6000610180516001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015620004c9575060408051601f3d908101601f19168201909252620004c69181019062000a07565b60015b620004d957620003f343620005b0565b919050565b600063ffffffff821115620004635760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840162000283565b6000806200055585858562000619565b915091505b935093915050565b80546000908015620005a6576200058e836200058060018462000a31565b600091825260209091200190565b5464010000000090046001600160e01b0316620005a9565b60005b9392505050565b600065ffffffffffff821115620004635760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b606482015260840162000283565b8254600090819080156200076e5760006200063b876200058060018562000a31565b60408051808201909152905463ffffffff8082168084526401000000009092046001600160e01b031660208401529192509087161015620006bf5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b6579730000000000604482015260640162000283565b805163ffffffff8088169116036200070d5784620006e4886200058060018662000a31565b80546001600160e01b03929092166401000000000263ffffffff9092169190911790556200075d565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216640100000000029216919091179101555b6020015192508391506200055a9050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a8152918220955192519093166401000000000291909316179201919091559050816200055a565b6001600160a01b0381168114620007df57600080fd5b50565b60008060408385031215620007f657600080fd5b82516200080381620007c9565b60208401519092506200081681620007c9565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200084c57607f821691505b6020821081036200086d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620008c157600081815260208120601f850160051c810160208610156200089c5750805b601f850160051c820191505b81811015620008bd57828155600101620008a8565b5050505b505050565b81516001600160401b03811115620008e257620008e262000821565b620008fa81620008f3845462000837565b8462000873565b602080601f831160018114620009325760008415620009195750858301515b600019600386901b1c1916600185901b178555620008bd565b600085815260208120601f198616915b82811015620009635788860151825594840194600190910190840162000942565b5085821015620009825787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083528351808285015260005b81811015620009c157858101830151858201604001528201620009a3565b506000604082860101526040601f19601f8301168501019250505092915050565b805160208083015191908110156200086d5760001960209190910360031b1b16919050565b60006020828403121562000a1a57600080fd5b815165ffffffffffff81168114620005a957600080fd5b81810381811115620001fd57634e487b7160e01b600052601160045260246000fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c05161576662000b4a6000396000818161065c01526116d101526000818161050b01528181611c62015281816125cf01528181612779015281816127fd01528181612856015281816129970152612a13015260008181610c11015281816117c101528181611bb501528181611dda01528181612168015281816126ed015281816128ff0152612a8d015260008181610b5101526112ef015260006141870152600061415f01526000611b6101526000611b37015260006140ba015260006140e40152600061410e01526157666000f3fe60806040526004361061039b5760003560e01c806367e2e078116101dc578063c01f9e3711610102578063dea112a6116100a0578063f8ce560a1161006f578063f8ce560a14610b9f578063f945970a14610bbf578063fa25f37714610bdf578063fc0c546a14610bff57600080fd5b8063dea112a614610aeb578063deaaa7cc14610b0b578063e2fdcc1714610b3f578063f23a6e6114610b7357600080fd5b8063cf781d45116100dc578063cf781d4514610a45578063d152a32e14610a65578063d8bff44014610a85578063dd4e2ba514610aa557600080fd5b8063c01f9e37146109d9578063c28bc2fa14610a12578063c2e863e414610a2557600080fd5b80639f8b33921161017a578063b58131b011610149578063b58131b014610963578063b5cc143a14610978578063bc197c811461098d578063be443ad0146109b957600080fd5b80639f8b3392146108f8578063a67d06351461090e578063a7713a701461092e578063aedbfe331461094357600080fd5b806391ddadf4116101b657806391ddadf41461088357806391f36633146108af57806395b6d6bd146108cf57806397c3d334146108e457600080fd5b806367e2e0781461082557806384b0196e1461083b57806385f2aef21461086357600080fd5b80633e4f49e6116102c1578063544ffc9c1161025f57806360c4247f1161022e57806360c4247f1461079e57806360e69a7b146107be578063638663ac146107d157806364390ff1146107e657600080fd5b8063544ffc9c146106df57806354fd4d5014610734578063592a84941461075e57806359d46ffc1461077e57600080fd5b806349758df21161029b57806349758df21461067e5780634bf5d7e91461069e578063501fa8bd146106b3578063525f9c3e146106c957600080fd5b80633e4f49e6146105fd578063452115d61461062a57806346c96aac1461064a57600080fd5b8063150b7a02116103395780632d63f693116103085780632d63f6931461055d5780632fe3e26114610593578063380a243a146105c75780633932abb1146105e757600080fd5b8063150b7a02146104a05780631d28dec7146104d95780631f850716146104f957806322b36ac61461054557600080fd5b806306fdde031161037557806306fdde031461041e578063095cf5c6146104405780630f8a88361461046057806311fd26f41461048057600080fd5b806301ffc9a7146103a957806302a251a3146103de57806306f3f9e6146103fe57600080fd5b366103a457005b005b600080fd5b3480156103b557600080fd5b506103c96103c4366004614659565b610c33565b60405190151581526020015b60405180910390f35b3480156103ea57600080fd5b50620697805b6040519081526020016103d5565b34801561040a57600080fd5b506103a2610419366004614683565b610ca0565b34801561042a57600080fd5b50610433610d12565b6040516103d591906146ec565b34801561044c57600080fd5b506103a261045b366004614714565b610da4565b34801561046c57600080fd5b506103f061047b36600461495d565b610e18565b34801561048c57600080fd5b506103f061049b366004614a27565b6111bb565b3480156104ac57600080fd5b506104c06104bb366004614a5c565b6111e7565b6040516001600160e01b031990911681526020016103d5565b3480156104e557600080fd5b506103a26104f4366004614683565b6111f8565b34801561050557600080fd5b5061052d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103d5565b34801561055157600080fd5b506103f0633b9aca0081565b34801561056957600080fd5b506103f0610578366004614683565b6000908152600460205260409020546001600160401b031690565b34801561059f57600080fd5b506103f07fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156105d357600080fd5b506103a26105e2366004614b0f565b611230565b3480156105f357600080fd5b506202a3006103f0565b34801561060957600080fd5b5061061d610618366004614683565b61143f565b6040516103d59190614b77565b34801561063657600080fd5b506103f0610645366004614b9f565b61159b565b34801561065657600080fd5b5061052d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068a57600080fd5b506103a2610699366004614683565b6116aa565b3480156106aa57600080fd5b506104336117bd565b3480156106bf57600080fd5b506103f06101f481565b3480156106d557600080fd5b506103f060035481565b3480156106eb57600080fd5b506107196106fa366004614683565b6000908152600760205260409020805460018201546002909201549092565b604080519384526020840192909252908201526060016103d5565b34801561074057600080fd5b506040805180820190915260018152603160f81b6020820152610433565b34801561076a57600080fd5b506103a2610779366004614683565b61187f565b34801561078a57600080fd5b50600b5461052d906001600160a01b031681565b3480156107aa57600080fd5b506103f06107b9366004614683565b611900565b6103f06107cc366004614c2e565b6119b1565b3480156107dd57600080fd5b506103a2611ac3565b3480156107f257600080fd5b506103c9610801366004614cd4565b60009182526007602090815260408084209284526003909201905290205460ff1690565b34801561083157600080fd5b506103f061271081565b34801561084757600080fd5b50610850611b29565b6040516103d59796959493929190614d31565b34801561086f57600080fd5b50600a5461052d906001600160a01b031681565b34801561088f57600080fd5b50610898611bb1565b60405165ffffffffffff90911681526020016103d5565b3480156108bb57600080fd5b506103f06108ca366004614cd4565b611c3f565b3480156108db57600080fd5b506103a2611cea565b3480156108f057600080fd5b5060646103f0565b34801561090457600080fd5b506103f0600e5481565b34801561091a57600080fd5b50600d5461052d906001600160a01b031681565b34801561093a57600080fd5b506103f0611d69565b34801561094f57600080fd5b506103f061095e366004614c2e565b611d93565b34801561096f57600080fd5b506103f0611dd0565b34801561098457600080fd5b506103a2611e87565b34801561099957600080fd5b506104c06109a8366004614da1565b63bc197c8160e01b95945050505050565b3480156109c557600080fd5b506103f06109d4366004614e52565b611f06565b3480156109e557600080fd5b506103f06109f4366004614683565b6000908152600460205260409020600101546001600160401b031690565b6103a2610a20366004614edd565b611f5d565b348015610a3157600080fd5b506103f0610a40366004614f20565b61204f565b348015610a5157600080fd5b506103f0610a60366004614f87565b612098565b348015610a7157600080fd5b506103a2610a80366004614714565b6120af565b348015610a9157600080fd5b50600c5461052d906001600160a01b031681565b348015610ab157600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e90820152610433565b348015610af757600080fd5b506103f0610b06366004614fd1565b612123565b348015610b1757600080fd5b506103f07f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610b4b57600080fd5b5061052d7f000000000000000000000000000000000000000000000000000000000000000081565b348015610b7f57600080fd5b506104c0610b8e366004615006565b63f23a6e6160e01b95945050505050565b348015610bab57600080fd5b506103f0610bba366004614683565b612145565b348015610bcb57600080fd5b506103f0610bda36600461506e565b6121ef565b348015610beb57600080fd5b506103f0610bfa36600461511e565b6122e9565b348015610c0b57600080fd5b5061052d7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b031982166367276c3760e01b1480610c6457506001600160e01b03198216631debdb9560e31b145b80610c7f57506001600160e01b03198216630271189760e51b145b80610c9a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b333014610cef5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b610d06565b80610cff6005612355565b03610cf457505b610d0f816123d4565b50565b606060028054610d2190615186565b80601f0160208091040260200160405190810160405280929190818152602001828054610d4d90615186565b8015610d9a5780601f10610d6f57610100808354040283529160200191610d9a565b820191906000526020600020905b815481529060010190602001808311610d7d57829003601f168201915b5050505050905090565b6001600160a01b038116610dcb5760405163d92e233d60e01b815260040160405180910390fd5b600a546001600160a01b03163314610df657604051633a7cfa5d60e21b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60003381610e24611bb1565b65ffffffffffff169050610e36611dd0565b610e46838a61049b6001866151d6565b1015610eae5760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610ce6565b6000610ec4888888888051906020012087611d93565b90508651885114610ee75760405162461bcd60e51b8152600401610ce6906151e9565b8551885114610f085760405162461bcd60e51b8152600401610ce6906151e9565b6000885111610f595760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610ce6565b600081815260046020526040902054600160401b90046001600160a01b031615610fcf5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610ce6565b6000610fde6202a3008461522a565b90506000610fef620697808361522a565b905060405180610100016040528061100684612542565b6001600160401b031681526001600160a01b03871660208201526000604082015260600161103383612542565b6001600160401b0390811682526000602080840182905260408085018390526060808601849052608095860184905289845260048352928190208651815493880151888401519187166001600160e01b031990951694909417600160401b6001600160a01b039095168502176001600160e01b0316600160e01b60e092831c0217825593870151958701519585169590911c90910293909317600184015560a08401516002909301805460c0860151929095015161ffff1990951693151561ff00191693909317610100911515919091021762ff0000191662010000931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e9181111561115757611157614731565b60405190808252806020026020018201604052801561118a57816020015b60608152602001906001900390816111755790505b508d88888f6040516111a4999897969594939291906152cb565b60405180910390a150909998505050505050505050565b60006111dd8484846111d860408051602081019091526000815290565b6125ae565b90505b9392505050565b630a85bd0160e11b5b949350505050565b600c546001600160a01b0316331461122357604051636184ba1160e01b815260040160405180910390fd5b61122c81612b05565b5050565b600084815260046020526040812060609161124a8761143f565b9050600181600881111561126057611260614b61565b148061127d5750600081600881111561127b5761127b614b61565b145b6112c95760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206e6f7420616374697665206f722070656e64696e67006044820152606401610ce6565b81546001600160401b03163360006112e3828a85896125ae565b905060006127106003547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638e539e8c876040518263ffffffff1660e01b815260040161133b91815260200190565b602060405180830381865afa158015611358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137c91906153a2565b61138691906153bb565b61139091906153e8565b90508082116113ed5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20696e73756666696369656e7420766f74696e6720706f6044820152623bb2b960e91b6064820152608401610ce6565b89836001600160a01b03168c7fdb700dee4c69422ecdfd4ad68ffe25aa39c6ddffef4657f727571e095b642cc58c8c60405161142a9291906153fc565b60405180910390a45050505050505050505050565b6000818152600460205260408120600281015460ff16156114635750600792915050565b6002810154610100900460ff161561147e5750600292915050565b600281015462010000900460ff161561149a5750600892915050565b6000838152600460205260408120546001600160401b0316908190036115025760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610ce6565b600061150c611bb1565b65ffffffffffff16905080821061152857506000949350505050565b6000858152600460205260409020600101546001600160401b03168181106115565750600195945050505050565b61155f86612c30565b801561157e575060008681526007602052604090208054600190910154115b1561158f5750600495945050505050565b50600395945050505050565b600033816115ac8787878786611d93565b905060006115b98261143f565b60088111156115ca576115ca614b61565b146116175760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e6f723a20746f6f206c61746520746f2063616e63656c000000006044820152606401610ce6565b6000818152600460205260409020546001600160a01b03838116600160401b90920416146116925760405162461bcd60e51b815260206004820152602260248201527f476f7665726e6f723a206f6e6c792070726f706f7365722063616e2063616e63604482015261195b60f21b6064820152608401610ce6565b61169f8787878786612c7c565b979650505050505050565b633b9aca008111156116cf57604051634fa0e5e360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa15801561172d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611751919061542b565b6001600160a01b0316336001600160a01b03161461178257604051633b8d9d7560e21b815260040160405180910390fd5b60038190556040518181527f5abd4079db52a376d0f48814132d5f1f10624699a317971509682d7ec6db0a4f9060200160405180910390a150565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634bf5d7e96040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561183e57506040513d6000823e601f3d908101601f1916820160405261183b9190810190615448565b60015b61187a575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b600a546001600160a01b031633146118aa57604051633a7cfa5d60e21b815260040160405180910390fd5b6101f48111156118cd576040516314263b7360e11b815260040160405180910390fd5b600e81905560405181907f586fc658003980a786f5709cd2ad386034e0424082c948c863d3116f8f66566990600090a250565b600954600090808203611917575050600854919050565b600060096119266001846151d6565b81548110611936576119366154b5565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b0316928201929092529150841061198c57602001516001600160e01b03169392505050565b6119a061199885612dba565b600990612e1f565b6001600160e01b0316949350505050565b6000806119c18787878787611d93565b905060006119ce8261143f565b905060048160088111156119e4576119e4614b61565b14611a3b5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b6064820152608401610ce6565b60008281526004602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90611a899084815260200190565b60405180910390a1611a9e8289898989612ed2565b611aab8289898989612f5c565b611ab88289898989612ed2565b509695505050505050565b600c546001600160a01b03163314611aee57604051636184ba1160e01b815260040160405180910390fd5b600c80546001600160a01b03191690556040517f62acb1bd035e6b0070db32c18d981d7ef3d5921d59efd75de499c7632df8dd7990600090a1565b600060608082808083611b5c7f00000000000000000000000000000000000000000000000000000000000000008361305e565b611b877f0000000000000000000000000000000000000000000000000000000000000000600161305e565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611c2d575060408051601f3d908101601f19168201909252611c2a918101906154cb565b60015b61187a57611c3a4361310a565b905090565b6040516331a9108f60e11b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccd919061542b565b90506111f0818585604051806020016040528060008152506125ae565b600d546001600160a01b03163314611d155760405163f37fda0760e01b815260040160405180910390fd5b600d8054600c80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517f03ae59c1e4263c9049c7aab44b77283fa0484d5d0f714e102cd9857f8fc5274d90600090a2565b60095460009015611d8c57611d7e6009613171565b6001600160e01b0316905090565b5060085490565b60008585858585604051602001611dae9594939291906154f3565b60408051601f1981840301815291905280516020909101209695505050505050565b6000612710600e547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638e539e8c600142611e1491906151d6565b6040518263ffffffff1660e01b8152600401611e3291815260200190565b602060405180830381865afa158015611e4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7391906153a2565b611e7d91906153bb565b611c3a91906153e8565b600b546001600160a01b03163314611eb25760405163071110c760e51b815260040160405180910390fd5b600b8054600a80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517fe25466fe8250322bee73bc230e10775fe0da57be723ebdabfdc8b62b4ba0d10c90600090a2565b600080339050611f518882898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506131aa915050565b98975050505050505050565b333014611fa75760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b6044820152606401610ce6565b611fbe565b80611fb76005612355565b03611fac57505b600080856001600160a01b0316858585604051611fdc929190615176565b60006040518083038185875af1925050503d8060008114612019576040519150601f19603f3d011682016040523d82523d6000602084013e61201e565b606091505b509150915061204682826040518060600160405280602881526020016156e260289139613304565b50505050505050565b60008033905061169f8782888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331d92505050565b60006120a6858585856125ae565b95945050505050565b600c546001600160a01b031633146120da57604051636184ba1160e01b815260040160405180910390fd5b6001600160a01b0381166121015760405163d92e233d60e01b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000803390506120a6858286866040518060200160405280600081525061331d565b6000606461215283611900565b604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa1580156121b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121db91906153a2565b6121e591906153bb565b610c9a91906153e8565b60008061229361228b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888d8c8c8c60405161222b929190615176565b60405180910390208b80519060200120604051602001612270959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061334b565b868686613378565b90506122da8b828c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506131aa915050565b9b9a5050505050505050505050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810187905260ff8516606082015260009081906123379061228b90608001612270565b9050611f51888289896040518060200160405280600081525061331d565b60006123708254600f81810b600160801b909204900b131590565b1561238e57604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b60648111156124575760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610ce6565b6000612461611d69565b905080158015906124725750600954155b156124d657604080518082019091526000815260099060208101612495846133a0565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b6125036124f16124e4611bb1565b65ffffffffffff16612dba565b6124fa846133a0565b60099190613409565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60006001600160401b038211156125aa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610ce6565b5090565b60405161f8e560ef1b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637c72800090602401602060405180830381865afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a919061554f565b9050600281600281111561265057612650614b61565b036126a75760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a206d616e61676564206e66742063616e6e6f7420766f746044820152606560f81b6064820152608401610ce6565b60008160028111156126bb576126bb614b61565b0361276057604051634d6fb77560e01b81526001600160a01b03878116600483015260248201879052604482018690527f00000000000000000000000000000000000000000000000000000000000000001690634d6fb77590606401602060405180830381865afa158015612734573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275891906153a2565b9150506111f0565b6040516319a0a9d560e01b8152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906319a0a9d590602401602060405180830381865afa1580156127c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ec91906153a2565b905060006128246001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168388613424565b604051631e09967560e31b81526004810184905265ffffffffffff821660248201529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f04cb3a890604401608060405180830381865afa15801561289d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c19190615570565b60600151905080600003612a6057604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990526000917f000000000000000000000000000000000000000000000000000000000000000090911690634d6fb77590606401602060405180830381865afa158015612948573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296c91906153a2565b60405163145615f560e21b8152600481018b9052602481018690529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063515857d490604401602060405180830381865afa1580156129de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0291906153a2565b90506000612a3b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016878d8d613715565b905082612a48828461522a565b612a52919061522a565b9750505050505050506111f0565b604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990527f00000000000000000000000000000000000000000000000000000000000000001690634d6fb77590606401602060405180830381865afa158015612ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af891906153a2565b9998505050505050505050565b600080612b118361143f565b90506008816008811115612b2757612b27614b61565b14158015612b4757506002816008811115612b4457612b44614b61565b14155b8015612b6557506005816008811115612b6257612b62614b61565b14155b8015612b8357506007816008811115612b8057612b80614b61565b14155b612bcf5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610ce6565b60008381526004602052604090819020600201805462ff0000191662010000179055517fde0cea2a3a0097cc3d981d40c375407760e85bc9c5e69aea449ac3885f8615c690612c219085815260200190565b60405180910390a15090919050565b600081815260076020526040812060028101546001820154612c52919061522a565b600084815260046020526040902054612c73906001600160401b0316612145565b11159392505050565b600080612c8c8787878787611d93565b90506000612c998261143f565b90506008816008811115612caf57612caf614b61565b14158015612ccf57506002816008811115612ccc57612ccc614b61565b14155b8015612ced57506005816008811115612cea57612cea614b61565b14155b8015612d0b57506007816008811115612d0857612d08614b61565b14155b612d575760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610ce6565b60008281526004602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c90612da79084815260200190565b60405180910390a1509695505050505050565b600063ffffffff8211156125aa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610ce6565b815460009081816005811115612e7c576000612e3a84613cfc565b612e4490856151d6565b60008881526020902090915081015463ffffffff9081169087161015612e6c57809150612e7a565b612e7781600161522a565b92505b505b6000612e8a87878585613de4565b90508015612ec557612eaf87612ea16001846151d6565b600091825260209091200190565b54600160201b90046001600160e01b031661169f565b6000979650505050505050565b612f55565b8181101561204657306001600160a01b0316868281518110612efb57612efb6154b5565b60200260200101516001600160a01b031603612f4557612f45848281518110612f2657612f266154b5565b6020026020010151805190602001206005613e4290919063ffffffff16565b612f4e816155db565b9050612ed7565b5050505050565b600060405180606001604052806027815260200161570a60279139855190915060005b8181101561305457600080888381518110612f9c57612f9c6154b5565b60200260200101516001600160a01b0316888481518110612fbf57612fbf6154b5565b6020026020010151888581518110612fd957612fd96154b5565b6020026020010151604051612fee91906155f4565b60006040518083038185875af1925050503d806000811461302b576040519150601f19603f3d011682016040523d82523d6000602084013e613030565b606091505b5091509150613040828287613304565b5050508061304d906155db565b9050612f7f565b5050505050505050565b606060ff8316156130795761307283613e7e565b9050610c9a565b81805461308590615186565b80601f01602080910402602001604051908101604052809291908181526020018280546130b190615186565b80156130fe5780601f106130d3576101008083540402835291602001916130fe565b820191906000526020600020905b8154815290600101906020018083116130e157829003601f168201915b50505050509050610c9a565b600065ffffffffffff8211156125aa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610ce6565b805460009080156131a15761318b83612ea16001846151d6565b54600160201b90046001600160e01b03166111e0565b60009392505050565b600086815260046020526040812060016131c38961143f565b60088111156131d4576131d4614b61565b1461322d5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610ce6565b805460009061324990899089906001600160401b0316876125ae565b90506132588988888488613eb3565b83516000036132ae5786886001600160a01b03167f02ecdb7f59712b7ae7cb6851cce1c64e98f94e5b51ec63809112c054622b25548b89858a6040516132a19493929190615610565b60405180910390a3611f51565b86886001600160a01b03167f7dcdc52e34b09364e599a32b0e3ccb5b730a7b952ddbdf4f237ea785da228ce78b89858a8a6040516132f0959493929190615638565b60405180910390a398975050505050505050565b606083156133135750816111e0565b6111e08383614083565b6000613341868686868661333c60408051602081019091526000815290565b6131aa565b9695505050505050565b6000610c9a6133586140ad565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000613389878787876141d8565b915091506133968161429c565b5095945050505050565b60006001600160e01b038211156125aa5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610ce6565b6000806134178585856143e6565b915091505b935093915050565b604051635058979360e01b81526004810183905260009081906001600160a01b03861690635058979390602401602060405180830381865afa15801561346e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349291906154cb565b90508065ffffffffffff166000036134ae5760009150506111e0565b826001600160a01b03861663f04cb3a8866134ca600186615672565b6040516001600160e01b031960e085901b168152600481019290925265ffffffffffff166024820152604401608060405180830381865afa158015613513573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135379190615570565b511161355057613548600182615672565b9150506111e0565b604051631e09967560e31b8152600481018590526000602482015283906001600160a01b0387169063f04cb3a890604401608060405180830381865afa15801561359e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c29190615570565b5111156135d35760009150506111e0565b6000806135e1600184615672565b905061361760405180608001604052806000815260200160006001600160a01b0316815260200160008152602001600081525090565b8265ffffffffffff168265ffffffffffff161115613709576000600261363d8585615672565b6136479190615698565b6136519084615672565b604051631e09967560e31b8152600481018a905265ffffffffffff821660248201529091506001600160a01b038a169063f04cb3a890604401608060405180830381865afa1580156136a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136cb9190615570565b9150868260000151036136e45794506111e09350505050565b81518711156136f557809350613703565b613700600182615672565b92505b50613617565b50909695505050505050565b60405163539c6d4160e11b81526004810184905260009081906001600160a01b0387169063a738da8290602401602060405180830381865afa15801561375f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613783919061542b565b604051635058979360e01b8152600481018690529091506001600160a01b03821690635058979390602401602060405180830381865afa1580156137cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ef91906153a2565b6000036138005760009150506111f0565b6000866001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613840573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613864919061542b565b60405163f25e55a560e01b81526001600160a01b0380831660048301526024820188905291925060009160019183916138f0919087169063f25e55a590604401602060405180830381865afa1580156138c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138e591906153a2565b62093a808106900390565b6040516328a3532760e21b8152600481018a9052602481018290529091506000906001600160a01b0387169063a28d4c9c90604401602060405180830381865afa158015613942573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396691906153a2565b604051631277308160e21b8152600481018b90526024810182905290915060009081906001600160a01b038916906349dcc204906044016040805180830381865afa1580156139b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dd91906156bd565b90925090506139f38462093a8084068403614585565b9350600062093a80613a0b86828e068e0383016151d6565b613a1591906153e8565b905060008115613ce95760005b82811015613ce7576001600160a01b038b1663a28d4c9c8f6001613a4962093a808c61522a565b613a5391906151d6565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015613a94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab891906153a2565b95508a6001600160a01b03166349dcc2048f886040518363ffffffff1660e01b8152600401613af1929190918252602082015260400190565b6040805180830381865afa158015613b0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b3191906156bd565b90955093506001600160a01b038b1663f7412baf816376f4be366001613b5a62093a808d61522a565b613b6491906151d6565b6040518263ffffffff1660e01b8152600401613b8291815260200190565b602060405180830381865afa158015613b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc391906153a2565b6040518263ffffffff1660e01b8152600401613be191815260200190565b6040805180830381865afa158015613bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2191906156bd565b9250613c309050826001614585565b6040516392777b2960e01b81526001600160a01b038c81166004830152602482018a905291995089918d16906392777b2990604401602060405180830381865afa158015613c82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ca691906153a2565b613cb090866153bb565b613cba91906153e8565b613cc4908a61522a565b9850613cd362093a808861522a565b965080613cdf816155db565b915050613a22565b505b50959d9c50505050505050505050505050565b600081600003613d0e57506000919050565b60006001613d1b8461459b565b901c6001901b90506001818481613d3457613d346153d2565b048201901c90506001818481613d4c57613d4c6153d2565b048201901c90506001818481613d6457613d646153d2565b048201901c90506001818481613d7c57613d7c6153d2565b048201901c90506001818481613d9457613d946153d2565b048201901c90506001818481613dac57613dac6153d2565b048201901c90506001818481613dc457613dc46153d2565b048201901c90506111e081828581613dde57613dde6153d2565b0461462f565b60005b81831015613e3a576000613dfb848461463e565b60008781526020902090915063ffffffff86169082015463ffffffff161115613e2657809250613e34565b613e3181600161522a565b93505b50613de7565b509392505050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60408051602080825281830190925260609160ff84169160009180820181803683375050509182525060208101929092525090565b6000858152600760209081526040808320878452600381019092529091205460ff1615613f325760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b6064820152608401610ce6565b60008311613f935760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72566f74696e6753696d706c653a207a65726f20766f74696e60448201526719c81dd95a59da1d60c21b6064820152608401610ce6565b60008581526003820160205260409020805460ff1916600117905560ff8416613fd55782816000016000828254613fca919061522a565b9091555061407b9050565b60001960ff851601613ff55782816001016000828254613fca919061522a565b60011960ff8516016140155782816002016000828254613fca919061522a565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b6064820152608401610ce6565b505050505050565b8151156140935781518083602001fd5b8060405162461bcd60e51b8152600401610ce691906146ec565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561410657507f000000000000000000000000000000000000000000000000000000000000000046145b1561413057507f000000000000000000000000000000000000000000000000000000000000000090565b611c3a604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561420f5750600090506003614293565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614263573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661428c57600060019250925050614293565b9150600090505b94509492505050565b60008160048111156142b0576142b0614b61565b036142b85750565b60018160048111156142cc576142cc614b61565b036143195760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610ce6565b600281600481111561432d5761432d614b61565b0361437a5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610ce6565b600381600481111561438e5761438e614b61565b03610d0f5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610ce6565b82546000908190801561452c57600061440487612ea16001856151d6565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156144855760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610ce6565b805163ffffffff8088169116036144cd57846144a688612ea16001866151d6565b80546001600160e01b0392909216600160201b0263ffffffff90921691909117905561451c565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b60200151925083915061341c9050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b02919093161792019190915590508161341c565b600081831161459457816111e0565b5090919050565b600080608083901c156145b057608092831c92015b604083901c156145c257604092831c92015b602083901c156145d457602092831c92015b601083901c156145e657601092831c92015b600883901c156145f857600892831c92015b600483901c1561460a57600492831c92015b600283901c1561461c57600292831c92015b600183901c15610c9a5760010192915050565b600081831061459457816111e0565b600061464d60028484186153e8565b6111e09084841661522a565b60006020828403121561466b57600080fd5b81356001600160e01b0319811681146111e057600080fd5b60006020828403121561469557600080fd5b5035919050565b60005b838110156146b757818101518382015260200161469f565b50506000910152565b600081518084526146d881602086016020860161469c565b601f01601f19169290920160200192915050565b6020815260006111e060208301846146c0565b6001600160a01b0381168114610d0f57600080fd5b60006020828403121561472657600080fd5b81356111e0816146ff565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561476f5761476f614731565b604052919050565b60006001600160401b0382111561479057614790614731565b5060051b60200190565b600082601f8301126147ab57600080fd5b813560206147c06147bb83614777565b614747565b82815260059290921b840181019181810190868411156147df57600080fd5b8286015b84811015611ab85780356147f6816146ff565b83529183019183016147e3565b600082601f83011261481457600080fd5b813560206148246147bb83614777565b82815260059290921b8401810191818101908684111561484357600080fd5b8286015b84811015611ab85780358352918301918301614847565b60006001600160401b0382111561487757614877614731565b50601f01601f191660200190565b60006148936147bb8461485e565b90508281528383830111156148a757600080fd5b828260208301376000602084830101529392505050565b600082601f8301126148cf57600080fd5b6111e083833560208501614885565b600082601f8301126148ef57600080fd5b813560206148ff6147bb83614777565b82815260059290921b8401810191818101908684111561491e57600080fd5b8286015b84811015611ab85780356001600160401b038111156149415760008081fd5b61494f8986838b01016148be565b845250918301918301614922565b600080600080600060a0868803121561497557600080fd5b8535945060208601356001600160401b038082111561499357600080fd5b61499f89838a0161479a565b955060408801359150808211156149b557600080fd5b6149c189838a01614803565b945060608801359150808211156149d757600080fd5b6149e389838a016148de565b935060808801359150808211156149f957600080fd5b508601601f81018813614a0b57600080fd5b614a1a88823560208401614885565b9150509295509295909350565b600080600060608486031215614a3c57600080fd5b8335614a47816146ff565b95602085013595506040909401359392505050565b60008060008060808587031215614a7257600080fd5b8435614a7d816146ff565b93506020850135614a8d816146ff565b92506040850135915060608501356001600160401b03811115614aaf57600080fd5b614abb878288016148be565b91505092959194509250565b60008083601f840112614ad957600080fd5b5081356001600160401b03811115614af057600080fd5b602083019150836020828501011115614b0857600080fd5b9250929050565b60008060008060608587031215614b2557600080fd5b843593506020850135925060408501356001600160401b03811115614b4957600080fd5b614b5587828801614ac7565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b6020810160098310614b9957634e487b7160e01b600052602160045260246000fd5b91905290565b60008060008060808587031215614bb557600080fd5b84356001600160401b0380821115614bcc57600080fd5b614bd88883890161479a565b95506020870135915080821115614bee57600080fd5b614bfa88838901614803565b94506040870135915080821115614c1057600080fd5b50614c1d878288016148de565b949793965093946060013593505050565b600080600080600060a08688031215614c4657600080fd5b85356001600160401b0380821115614c5d57600080fd5b614c6989838a0161479a565b96506020880135915080821115614c7f57600080fd5b614c8b89838a01614803565b95506040880135915080821115614ca157600080fd5b50614cae888289016148de565b935050606086013591506080860135614cc6816146ff565b809150509295509295909350565b60008060408385031215614ce757600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015614d2657815187529582019590820190600101614d0a565b509495945050505050565b60ff60f81b8816815260e060208201526000614d5060e08301896146c0565b8281036040840152614d6281896146c0565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050614d938185614cf6565b9a9950505050505050505050565b600080600080600060a08688031215614db957600080fd5b8535614dc4816146ff565b94506020860135614dd4816146ff565b935060408601356001600160401b0380821115614df057600080fd5b614dfc89838a01614803565b94506060880135915080821115614e1257600080fd5b614e1e89838a01614803565b93506080880135915080821115614e3457600080fd5b50614a1a888289016148be565b803560ff8116811461187a57600080fd5b60008060008060008060a08789031215614e6b57600080fd5b8635955060208701359450614e8260408801614e41565b935060608701356001600160401b0380821115614e9e57600080fd5b614eaa8a838b01614ac7565b90955093506080890135915080821115614ec357600080fd5b50614ed089828a016148be565b9150509295509295509295565b60008060008060608587031215614ef357600080fd5b8435614efe816146ff565b93506020850135925060408501356001600160401b03811115614b4957600080fd5b600080600080600060808688031215614f3857600080fd5b8535945060208601359350614f4f60408701614e41565b925060608601356001600160401b03811115614f6a57600080fd5b614f7688828901614ac7565b969995985093965092949392505050565b60008060008060808587031215614f9d57600080fd5b8435614fa8816146ff565b9350602085013592506040850135915060608501356001600160401b03811115614aaf57600080fd5b600080600060608486031215614fe657600080fd5b8335925060208401359150614ffd60408501614e41565b90509250925092565b600080600080600060a0868803121561501e57600080fd5b8535615029816146ff565b94506020860135615039816146ff565b9350604086013592506060860135915060808601356001600160401b0381111561506257600080fd5b614a1a888289016148be565b60008060008060008060008060006101008a8c03121561508d57600080fd5b8935985060208a013597506150a460408b01614e41565b965060608a01356001600160401b03808211156150c057600080fd5b6150cc8d838e01614ac7565b909850965060808c01359150808211156150e557600080fd5b506150f28c828d016148be565b94505061510160a08b01614e41565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060c0878903121561513757600080fd5b863595506020870135945061514e60408801614e41565b935061515c60608801614e41565b92506080870135915060a087013590509295509295509295565b8183823760009101908152919050565b600181811c9082168061519a57607f821691505b6020821081036151ba57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c9a57610c9a6151c0565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b80820180821115610c9a57610c9a6151c0565b600081518084526020808501945080840160005b83811015614d265781516001600160a01b031687529582019590820190600101615251565b600081518084526020808501808196508360051b8101915082860160005b858110156152be5782840389526152ac8483516146c0565b98850198935090840190600101615294565b5091979650505050505050565b60006101208b8352602060018060a01b038c16818501528160408501526152f48285018c61523d565b91508382036060850152615308828b614cf6565b915083820360808501528189518084528284019150828160051b850101838c0160005b8381101561535957601f198784030185526153478383516146c0565b9486019492509085019060010161532b565b505086810360a088015261536d818c615276565b9450505050508560c08401528460e084015282810361010084015261539281856146c0565b9c9b505050505050505050505050565b6000602082840312156153b457600080fd5b5051919050565b8082028115828204841417610c9a57610c9a6151c0565b634e487b7160e01b600052601260045260246000fd5b6000826153f7576153f76153d2565b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561543d57600080fd5b81516111e0816146ff565b60006020828403121561545a57600080fd5b81516001600160401b0381111561547057600080fd5b8201601f8101841361548157600080fd5b805161548f6147bb8261485e565b8181528560208385010111156154a457600080fd5b6120a682602083016020860161469c565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156154dd57600080fd5b815165ffffffffffff811681146111e057600080fd5b60a08152600061550660a083018861523d565b82810360208401526155188188614cf6565b9050828103604084015261552c8187615276565b606084019590955250506001600160a01b03919091166080909101529392505050565b60006020828403121561556157600080fd5b8151600381106111e057600080fd5b60006080828403121561558257600080fd5b604051608081018181106001600160401b03821117156155a4576155a4614731565b6040528251815260208301516155b9816146ff565b6020820152604083810151908201526060928301519281019290925250919050565b6000600182016155ed576155ed6151c0565b5060010190565b6000825161560681846020870161469c565b9190910192915050565b84815260ff8416602082015282604082015260806060820152600061334160808301846146c0565b85815260ff8516602082015283604082015260a06060820152600061566060a08301856146c0565b8281036080840152611f5181856146c0565b65ffffffffffff828116828216039080821115615691576156916151c0565b5092915050565b600065ffffffffffff808416806156b1576156b16153d2565b92169190910492915050565b600080604083850312156156d057600080fd5b50508051602090910151909290915056fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a2646970667358221220129f3447433c59a981e767b2f1452563adddce84ada246938e565b4cf0250b8564736f6c63430008130033000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1100000000000000000000000050a459fc0069843750091d6382afc960d0b22b6d

Deployed Bytecode

0x60806040526004361061039b5760003560e01c806367e2e078116101dc578063c01f9e3711610102578063dea112a6116100a0578063f8ce560a1161006f578063f8ce560a14610b9f578063f945970a14610bbf578063fa25f37714610bdf578063fc0c546a14610bff57600080fd5b8063dea112a614610aeb578063deaaa7cc14610b0b578063e2fdcc1714610b3f578063f23a6e6114610b7357600080fd5b8063cf781d45116100dc578063cf781d4514610a45578063d152a32e14610a65578063d8bff44014610a85578063dd4e2ba514610aa557600080fd5b8063c01f9e37146109d9578063c28bc2fa14610a12578063c2e863e414610a2557600080fd5b80639f8b33921161017a578063b58131b011610149578063b58131b014610963578063b5cc143a14610978578063bc197c811461098d578063be443ad0146109b957600080fd5b80639f8b3392146108f8578063a67d06351461090e578063a7713a701461092e578063aedbfe331461094357600080fd5b806391ddadf4116101b657806391ddadf41461088357806391f36633146108af57806395b6d6bd146108cf57806397c3d334146108e457600080fd5b806367e2e0781461082557806384b0196e1461083b57806385f2aef21461086357600080fd5b80633e4f49e6116102c1578063544ffc9c1161025f57806360c4247f1161022e57806360c4247f1461079e57806360e69a7b146107be578063638663ac146107d157806364390ff1146107e657600080fd5b8063544ffc9c146106df57806354fd4d5014610734578063592a84941461075e57806359d46ffc1461077e57600080fd5b806349758df21161029b57806349758df21461067e5780634bf5d7e91461069e578063501fa8bd146106b3578063525f9c3e146106c957600080fd5b80633e4f49e6146105fd578063452115d61461062a57806346c96aac1461064a57600080fd5b8063150b7a02116103395780632d63f693116103085780632d63f6931461055d5780632fe3e26114610593578063380a243a146105c75780633932abb1146105e757600080fd5b8063150b7a02146104a05780631d28dec7146104d95780631f850716146104f957806322b36ac61461054557600080fd5b806306fdde031161037557806306fdde031461041e578063095cf5c6146104405780630f8a88361461046057806311fd26f41461048057600080fd5b806301ffc9a7146103a957806302a251a3146103de57806306f3f9e6146103fe57600080fd5b366103a457005b005b600080fd5b3480156103b557600080fd5b506103c96103c4366004614659565b610c33565b60405190151581526020015b60405180910390f35b3480156103ea57600080fd5b50620697805b6040519081526020016103d5565b34801561040a57600080fd5b506103a2610419366004614683565b610ca0565b34801561042a57600080fd5b50610433610d12565b6040516103d591906146ec565b34801561044c57600080fd5b506103a261045b366004614714565b610da4565b34801561046c57600080fd5b506103f061047b36600461495d565b610e18565b34801561048c57600080fd5b506103f061049b366004614a27565b6111bb565b3480156104ac57600080fd5b506104c06104bb366004614a5c565b6111e7565b6040516001600160e01b031990911681526020016103d5565b3480156104e557600080fd5b506103a26104f4366004614683565b6111f8565b34801561050557600080fd5b5061052d7f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1181565b6040516001600160a01b0390911681526020016103d5565b34801561055157600080fd5b506103f0633b9aca0081565b34801561056957600080fd5b506103f0610578366004614683565b6000908152600460205260409020546001600160401b031690565b34801561059f57600080fd5b506103f07fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156105d357600080fd5b506103a26105e2366004614b0f565b611230565b3480156105f357600080fd5b506202a3006103f0565b34801561060957600080fd5b5061061d610618366004614683565b61143f565b6040516103d59190614b77565b34801561063657600080fd5b506103f0610645366004614b9f565b61159b565b34801561065657600080fd5b5061052d7f00000000000000000000000050a459fc0069843750091d6382afc960d0b22b6d81565b34801561068a57600080fd5b506103a2610699366004614683565b6116aa565b3480156106aa57600080fd5b506104336117bd565b3480156106bf57600080fd5b506103f06101f481565b3480156106d557600080fd5b506103f060035481565b3480156106eb57600080fd5b506107196106fa366004614683565b6000908152600760205260409020805460018201546002909201549092565b604080519384526020840192909252908201526060016103d5565b34801561074057600080fd5b506040805180820190915260018152603160f81b6020820152610433565b34801561076a57600080fd5b506103a2610779366004614683565b61187f565b34801561078a57600080fd5b50600b5461052d906001600160a01b031681565b3480156107aa57600080fd5b506103f06107b9366004614683565b611900565b6103f06107cc366004614c2e565b6119b1565b3480156107dd57600080fd5b506103a2611ac3565b3480156107f257600080fd5b506103c9610801366004614cd4565b60009182526007602090815260408084209284526003909201905290205460ff1690565b34801561083157600080fd5b506103f061271081565b34801561084757600080fd5b50610850611b29565b6040516103d59796959493929190614d31565b34801561086f57600080fd5b50600a5461052d906001600160a01b031681565b34801561088f57600080fd5b50610898611bb1565b60405165ffffffffffff90911681526020016103d5565b3480156108bb57600080fd5b506103f06108ca366004614cd4565b611c3f565b3480156108db57600080fd5b506103a2611cea565b3480156108f057600080fd5b5060646103f0565b34801561090457600080fd5b506103f0600e5481565b34801561091a57600080fd5b50600d5461052d906001600160a01b031681565b34801561093a57600080fd5b506103f0611d69565b34801561094f57600080fd5b506103f061095e366004614c2e565b611d93565b34801561096f57600080fd5b506103f0611dd0565b34801561098457600080fd5b506103a2611e87565b34801561099957600080fd5b506104c06109a8366004614da1565b63bc197c8160e01b95945050505050565b3480156109c557600080fd5b506103f06109d4366004614e52565b611f06565b3480156109e557600080fd5b506103f06109f4366004614683565b6000908152600460205260409020600101546001600160401b031690565b6103a2610a20366004614edd565b611f5d565b348015610a3157600080fd5b506103f0610a40366004614f20565b61204f565b348015610a5157600080fd5b506103f0610a60366004614f87565b612098565b348015610a7157600080fd5b506103a2610a80366004614714565b6120af565b348015610a9157600080fd5b50600c5461052d906001600160a01b031681565b348015610ab157600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e90820152610433565b348015610af757600080fd5b506103f0610b06366004614fd1565b612123565b348015610b1757600080fd5b506103f07f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610b4b57600080fd5b5061052d7f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1181565b348015610b7f57600080fd5b506104c0610b8e366004615006565b63f23a6e6160e01b95945050505050565b348015610bab57600080fd5b506103f0610bba366004614683565b612145565b348015610bcb57600080fd5b506103f0610bda36600461506e565b6121ef565b348015610beb57600080fd5b506103f0610bfa36600461511e565b6122e9565b348015610c0b57600080fd5b5061052d7f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1181565b60006001600160e01b031982166367276c3760e01b1480610c6457506001600160e01b03198216631debdb9560e31b145b80610c7f57506001600160e01b03198216630271189760e51b145b80610c9a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b333014610cef5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b610d06565b80610cff6005612355565b03610cf457505b610d0f816123d4565b50565b606060028054610d2190615186565b80601f0160208091040260200160405190810160405280929190818152602001828054610d4d90615186565b8015610d9a5780601f10610d6f57610100808354040283529160200191610d9a565b820191906000526020600020905b815481529060010190602001808311610d7d57829003601f168201915b5050505050905090565b6001600160a01b038116610dcb5760405163d92e233d60e01b815260040160405180910390fd5b600a546001600160a01b03163314610df657604051633a7cfa5d60e21b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60003381610e24611bb1565b65ffffffffffff169050610e36611dd0565b610e46838a61049b6001866151d6565b1015610eae5760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610ce6565b6000610ec4888888888051906020012087611d93565b90508651885114610ee75760405162461bcd60e51b8152600401610ce6906151e9565b8551885114610f085760405162461bcd60e51b8152600401610ce6906151e9565b6000885111610f595760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610ce6565b600081815260046020526040902054600160401b90046001600160a01b031615610fcf5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610ce6565b6000610fde6202a3008461522a565b90506000610fef620697808361522a565b905060405180610100016040528061100684612542565b6001600160401b031681526001600160a01b03871660208201526000604082015260600161103383612542565b6001600160401b0390811682526000602080840182905260408085018390526060808601849052608095860184905289845260048352928190208651815493880151888401519187166001600160e01b031990951694909417600160401b6001600160a01b039095168502176001600160e01b0316600160e01b60e092831c0217825593870151958701519585169590911c90910293909317600184015560a08401516002909301805460c0860151929095015161ffff1990951693151561ff00191693909317610100911515919091021762ff0000191662010000931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e9181111561115757611157614731565b60405190808252806020026020018201604052801561118a57816020015b60608152602001906001900390816111755790505b508d88888f6040516111a4999897969594939291906152cb565b60405180910390a150909998505050505050505050565b60006111dd8484846111d860408051602081019091526000815290565b6125ae565b90505b9392505050565b630a85bd0160e11b5b949350505050565b600c546001600160a01b0316331461122357604051636184ba1160e01b815260040160405180910390fd5b61122c81612b05565b5050565b600084815260046020526040812060609161124a8761143f565b9050600181600881111561126057611260614b61565b148061127d5750600081600881111561127b5761127b614b61565b145b6112c95760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206e6f7420616374697665206f722070656e64696e67006044820152606401610ce6565b81546001600160401b03163360006112e3828a85896125ae565b905060006127106003547f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f116001600160a01b0316638e539e8c876040518263ffffffff1660e01b815260040161133b91815260200190565b602060405180830381865afa158015611358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137c91906153a2565b61138691906153bb565b61139091906153e8565b90508082116113ed5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20696e73756666696369656e7420766f74696e6720706f6044820152623bb2b960e91b6064820152608401610ce6565b89836001600160a01b03168c7fdb700dee4c69422ecdfd4ad68ffe25aa39c6ddffef4657f727571e095b642cc58c8c60405161142a9291906153fc565b60405180910390a45050505050505050505050565b6000818152600460205260408120600281015460ff16156114635750600792915050565b6002810154610100900460ff161561147e5750600292915050565b600281015462010000900460ff161561149a5750600892915050565b6000838152600460205260408120546001600160401b0316908190036115025760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610ce6565b600061150c611bb1565b65ffffffffffff16905080821061152857506000949350505050565b6000858152600460205260409020600101546001600160401b03168181106115565750600195945050505050565b61155f86612c30565b801561157e575060008681526007602052604090208054600190910154115b1561158f5750600495945050505050565b50600395945050505050565b600033816115ac8787878786611d93565b905060006115b98261143f565b60088111156115ca576115ca614b61565b146116175760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e6f723a20746f6f206c61746520746f2063616e63656c000000006044820152606401610ce6565b6000818152600460205260409020546001600160a01b03838116600160401b90920416146116925760405162461bcd60e51b815260206004820152602260248201527f476f7665726e6f723a206f6e6c792070726f706f7365722063616e2063616e63604482015261195b60f21b6064820152608401610ce6565b61169f8787878786612c7c565b979650505050505050565b633b9aca008111156116cf57604051634fa0e5e360e01b815260040160405180910390fd5b7f00000000000000000000000050a459fc0069843750091d6382afc960d0b22b6d6001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa15801561172d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611751919061542b565b6001600160a01b0316336001600160a01b03161461178257604051633b8d9d7560e21b815260040160405180910390fd5b60038190556040518181527f5abd4079db52a376d0f48814132d5f1f10624699a317971509682d7ec6db0a4f9060200160405180910390a150565b60607f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f116001600160a01b0316634bf5d7e96040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561183e57506040513d6000823e601f3d908101601f1916820160405261183b9190810190615448565b60015b61187a575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b600a546001600160a01b031633146118aa57604051633a7cfa5d60e21b815260040160405180910390fd5b6101f48111156118cd576040516314263b7360e11b815260040160405180910390fd5b600e81905560405181907f586fc658003980a786f5709cd2ad386034e0424082c948c863d3116f8f66566990600090a250565b600954600090808203611917575050600854919050565b600060096119266001846151d6565b81548110611936576119366154b5565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b0316928201929092529150841061198c57602001516001600160e01b03169392505050565b6119a061199885612dba565b600990612e1f565b6001600160e01b0316949350505050565b6000806119c18787878787611d93565b905060006119ce8261143f565b905060048160088111156119e4576119e4614b61565b14611a3b5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b6064820152608401610ce6565b60008281526004602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90611a899084815260200190565b60405180910390a1611a9e8289898989612ed2565b611aab8289898989612f5c565b611ab88289898989612ed2565b509695505050505050565b600c546001600160a01b03163314611aee57604051636184ba1160e01b815260040160405180910390fd5b600c80546001600160a01b03191690556040517f62acb1bd035e6b0070db32c18d981d7ef3d5921d59efd75de499c7632df8dd7990600090a1565b600060608082808083611b5c7f487964726f6d6574657220476f7665726e6f72000000000000000000000000138361305e565b611b877f3100000000000000000000000000000000000000000000000000000000000001600161305e565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60007f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f116001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611c2d575060408051601f3d908101601f19168201909252611c2a918101906154cb565b60015b61187a57611c3a4361310a565b905090565b6040516331a9108f60e11b81526004810183905260009081906001600160a01b037f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f111690636352211e90602401602060405180830381865afa158015611ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccd919061542b565b90506111f0818585604051806020016040528060008152506125ae565b600d546001600160a01b03163314611d155760405163f37fda0760e01b815260040160405180910390fd5b600d8054600c80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517f03ae59c1e4263c9049c7aab44b77283fa0484d5d0f714e102cd9857f8fc5274d90600090a2565b60095460009015611d8c57611d7e6009613171565b6001600160e01b0316905090565b5060085490565b60008585858585604051602001611dae9594939291906154f3565b60408051601f1981840301815291905280516020909101209695505050505050565b6000612710600e547f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f116001600160a01b0316638e539e8c600142611e1491906151d6565b6040518263ffffffff1660e01b8152600401611e3291815260200190565b602060405180830381865afa158015611e4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7391906153a2565b611e7d91906153bb565b611c3a91906153e8565b600b546001600160a01b03163314611eb25760405163071110c760e51b815260040160405180910390fd5b600b8054600a80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517fe25466fe8250322bee73bc230e10775fe0da57be723ebdabfdc8b62b4ba0d10c90600090a2565b600080339050611f518882898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506131aa915050565b98975050505050505050565b333014611fa75760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b6044820152606401610ce6565b611fbe565b80611fb76005612355565b03611fac57505b600080856001600160a01b0316858585604051611fdc929190615176565b60006040518083038185875af1925050503d8060008114612019576040519150601f19603f3d011682016040523d82523d6000602084013e61201e565b606091505b509150915061204682826040518060600160405280602881526020016156e260289139613304565b50505050505050565b60008033905061169f8782888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331d92505050565b60006120a6858585856125ae565b95945050505050565b600c546001600160a01b031633146120da57604051636184ba1160e01b815260040160405180910390fd5b6001600160a01b0381166121015760405163d92e233d60e01b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000803390506120a6858286866040518060200160405280600081525061331d565b6000606461215283611900565b604051632394e7a360e21b8152600481018590527f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f116001600160a01b031690638e539e8c90602401602060405180830381865afa1580156121b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121db91906153a2565b6121e591906153bb565b610c9a91906153e8565b60008061229361228b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888d8c8c8c60405161222b929190615176565b60405180910390208b80519060200120604051602001612270959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061334b565b868686613378565b90506122da8b828c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506131aa915050565b9b9a5050505050505050505050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810187905260ff8516606082015260009081906123379061228b90608001612270565b9050611f51888289896040518060200160405280600081525061331d565b60006123708254600f81810b600160801b909204900b131590565b1561238e57604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b60648111156124575760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610ce6565b6000612461611d69565b905080158015906124725750600954155b156124d657604080518082019091526000815260099060208101612495846133a0565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b6125036124f16124e4611bb1565b65ffffffffffff16612dba565b6124fa846133a0565b60099190613409565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60006001600160401b038211156125aa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610ce6565b5090565b60405161f8e560ef1b81526004810184905260009081906001600160a01b037f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f111690637c72800090602401602060405180830381865afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a919061554f565b9050600281600281111561265057612650614b61565b036126a75760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a206d616e61676564206e66742063616e6e6f7420766f746044820152606560f81b6064820152608401610ce6565b60008160028111156126bb576126bb614b61565b0361276057604051634d6fb77560e01b81526001600160a01b03878116600483015260248201879052604482018690527f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f111690634d6fb77590606401602060405180830381865afa158015612734573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275891906153a2565b9150506111f0565b6040516319a0a9d560e01b8152600481018690526000907f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f116001600160a01b0316906319a0a9d590602401602060405180830381865afa1580156127c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ec91906153a2565b905060006128246001600160a01b037f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f11168388613424565b604051631e09967560e31b81526004810184905265ffffffffffff821660248201529091506000906001600160a01b037f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f11169063f04cb3a890604401608060405180830381865afa15801561289d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c19190615570565b60600151905080600003612a6057604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990526000917f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1190911690634d6fb77590606401602060405180830381865afa158015612948573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296c91906153a2565b60405163145615f560e21b8152600481018b9052602481018690529091506000906001600160a01b037f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f11169063515857d490604401602060405180830381865afa1580156129de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0291906153a2565b90506000612a3b6001600160a01b037f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1116878d8d613715565b905082612a48828461522a565b612a52919061522a565b9750505050505050506111f0565b604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990527f000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f111690634d6fb77590606401602060405180830381865afa158015612ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af891906153a2565b9998505050505050505050565b600080612b118361143f565b90506008816008811115612b2757612b27614b61565b14158015612b4757506002816008811115612b4457612b44614b61565b14155b8015612b6557506005816008811115612b6257612b62614b61565b14155b8015612b8357506007816008811115612b8057612b80614b61565b14155b612bcf5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610ce6565b60008381526004602052604090819020600201805462ff0000191662010000179055517fde0cea2a3a0097cc3d981d40c375407760e85bc9c5e69aea449ac3885f8615c690612c219085815260200190565b60405180910390a15090919050565b600081815260076020526040812060028101546001820154612c52919061522a565b600084815260046020526040902054612c73906001600160401b0316612145565b11159392505050565b600080612c8c8787878787611d93565b90506000612c998261143f565b90506008816008811115612caf57612caf614b61565b14158015612ccf57506002816008811115612ccc57612ccc614b61565b14155b8015612ced57506005816008811115612cea57612cea614b61565b14155b8015612d0b57506007816008811115612d0857612d08614b61565b14155b612d575760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610ce6565b60008281526004602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c90612da79084815260200190565b60405180910390a1509695505050505050565b600063ffffffff8211156125aa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610ce6565b815460009081816005811115612e7c576000612e3a84613cfc565b612e4490856151d6565b60008881526020902090915081015463ffffffff9081169087161015612e6c57809150612e7a565b612e7781600161522a565b92505b505b6000612e8a87878585613de4565b90508015612ec557612eaf87612ea16001846151d6565b600091825260209091200190565b54600160201b90046001600160e01b031661169f565b6000979650505050505050565b612f55565b8181101561204657306001600160a01b0316868281518110612efb57612efb6154b5565b60200260200101516001600160a01b031603612f4557612f45848281518110612f2657612f266154b5565b6020026020010151805190602001206005613e4290919063ffffffff16565b612f4e816155db565b9050612ed7565b5050505050565b600060405180606001604052806027815260200161570a60279139855190915060005b8181101561305457600080888381518110612f9c57612f9c6154b5565b60200260200101516001600160a01b0316888481518110612fbf57612fbf6154b5565b6020026020010151888581518110612fd957612fd96154b5565b6020026020010151604051612fee91906155f4565b60006040518083038185875af1925050503d806000811461302b576040519150601f19603f3d011682016040523d82523d6000602084013e613030565b606091505b5091509150613040828287613304565b5050508061304d906155db565b9050612f7f565b5050505050505050565b606060ff8316156130795761307283613e7e565b9050610c9a565b81805461308590615186565b80601f01602080910402602001604051908101604052809291908181526020018280546130b190615186565b80156130fe5780601f106130d3576101008083540402835291602001916130fe565b820191906000526020600020905b8154815290600101906020018083116130e157829003601f168201915b50505050509050610c9a565b600065ffffffffffff8211156125aa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610ce6565b805460009080156131a15761318b83612ea16001846151d6565b54600160201b90046001600160e01b03166111e0565b60009392505050565b600086815260046020526040812060016131c38961143f565b60088111156131d4576131d4614b61565b1461322d5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610ce6565b805460009061324990899089906001600160401b0316876125ae565b90506132588988888488613eb3565b83516000036132ae5786886001600160a01b03167f02ecdb7f59712b7ae7cb6851cce1c64e98f94e5b51ec63809112c054622b25548b89858a6040516132a19493929190615610565b60405180910390a3611f51565b86886001600160a01b03167f7dcdc52e34b09364e599a32b0e3ccb5b730a7b952ddbdf4f237ea785da228ce78b89858a8a6040516132f0959493929190615638565b60405180910390a398975050505050505050565b606083156133135750816111e0565b6111e08383614083565b6000613341868686868661333c60408051602081019091526000815290565b6131aa565b9695505050505050565b6000610c9a6133586140ad565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000613389878787876141d8565b915091506133968161429c565b5095945050505050565b60006001600160e01b038211156125aa5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610ce6565b6000806134178585856143e6565b915091505b935093915050565b604051635058979360e01b81526004810183905260009081906001600160a01b03861690635058979390602401602060405180830381865afa15801561346e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349291906154cb565b90508065ffffffffffff166000036134ae5760009150506111e0565b826001600160a01b03861663f04cb3a8866134ca600186615672565b6040516001600160e01b031960e085901b168152600481019290925265ffffffffffff166024820152604401608060405180830381865afa158015613513573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135379190615570565b511161355057613548600182615672565b9150506111e0565b604051631e09967560e31b8152600481018590526000602482015283906001600160a01b0387169063f04cb3a890604401608060405180830381865afa15801561359e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c29190615570565b5111156135d35760009150506111e0565b6000806135e1600184615672565b905061361760405180608001604052806000815260200160006001600160a01b0316815260200160008152602001600081525090565b8265ffffffffffff168265ffffffffffff161115613709576000600261363d8585615672565b6136479190615698565b6136519084615672565b604051631e09967560e31b8152600481018a905265ffffffffffff821660248201529091506001600160a01b038a169063f04cb3a890604401608060405180830381865afa1580156136a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136cb9190615570565b9150868260000151036136e45794506111e09350505050565b81518711156136f557809350613703565b613700600182615672565b92505b50613617565b50909695505050505050565b60405163539c6d4160e11b81526004810184905260009081906001600160a01b0387169063a738da8290602401602060405180830381865afa15801561375f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613783919061542b565b604051635058979360e01b8152600481018690529091506001600160a01b03821690635058979390602401602060405180830381865afa1580156137cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ef91906153a2565b6000036138005760009150506111f0565b6000866001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613840573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613864919061542b565b60405163f25e55a560e01b81526001600160a01b0380831660048301526024820188905291925060009160019183916138f0919087169063f25e55a590604401602060405180830381865afa1580156138c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138e591906153a2565b62093a808106900390565b6040516328a3532760e21b8152600481018a9052602481018290529091506000906001600160a01b0387169063a28d4c9c90604401602060405180830381865afa158015613942573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396691906153a2565b604051631277308160e21b8152600481018b90526024810182905290915060009081906001600160a01b038916906349dcc204906044016040805180830381865afa1580156139b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dd91906156bd565b90925090506139f38462093a8084068403614585565b9350600062093a80613a0b86828e068e0383016151d6565b613a1591906153e8565b905060008115613ce95760005b82811015613ce7576001600160a01b038b1663a28d4c9c8f6001613a4962093a808c61522a565b613a5391906151d6565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015613a94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab891906153a2565b95508a6001600160a01b03166349dcc2048f886040518363ffffffff1660e01b8152600401613af1929190918252602082015260400190565b6040805180830381865afa158015613b0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b3191906156bd565b90955093506001600160a01b038b1663f7412baf816376f4be366001613b5a62093a808d61522a565b613b6491906151d6565b6040518263ffffffff1660e01b8152600401613b8291815260200190565b602060405180830381865afa158015613b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc391906153a2565b6040518263ffffffff1660e01b8152600401613be191815260200190565b6040805180830381865afa158015613bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2191906156bd565b9250613c309050826001614585565b6040516392777b2960e01b81526001600160a01b038c81166004830152602482018a905291995089918d16906392777b2990604401602060405180830381865afa158015613c82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ca691906153a2565b613cb090866153bb565b613cba91906153e8565b613cc4908a61522a565b9850613cd362093a808861522a565b965080613cdf816155db565b915050613a22565b505b50959d9c50505050505050505050505050565b600081600003613d0e57506000919050565b60006001613d1b8461459b565b901c6001901b90506001818481613d3457613d346153d2565b048201901c90506001818481613d4c57613d4c6153d2565b048201901c90506001818481613d6457613d646153d2565b048201901c90506001818481613d7c57613d7c6153d2565b048201901c90506001818481613d9457613d946153d2565b048201901c90506001818481613dac57613dac6153d2565b048201901c90506001818481613dc457613dc46153d2565b048201901c90506111e081828581613dde57613dde6153d2565b0461462f565b60005b81831015613e3a576000613dfb848461463e565b60008781526020902090915063ffffffff86169082015463ffffffff161115613e2657809250613e34565b613e3181600161522a565b93505b50613de7565b509392505050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60408051602080825281830190925260609160ff84169160009180820181803683375050509182525060208101929092525090565b6000858152600760209081526040808320878452600381019092529091205460ff1615613f325760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b6064820152608401610ce6565b60008311613f935760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72566f74696e6753696d706c653a207a65726f20766f74696e60448201526719c81dd95a59da1d60c21b6064820152608401610ce6565b60008581526003820160205260409020805460ff1916600117905560ff8416613fd55782816000016000828254613fca919061522a565b9091555061407b9050565b60001960ff851601613ff55782816001016000828254613fca919061522a565b60011960ff8516016140155782816002016000828254613fca919061522a565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b6064820152608401610ce6565b505050505050565b8151156140935781518083602001fd5b8060405162461bcd60e51b8152600401610ce691906146ec565b6000306001600160a01b037f000000000000000000000000cc94f67da67311b187407979ee94cd7b52c8f2701614801561410657507f000000000000000000000000000000000000000000000000000000000000009246145b1561413057507f8d03e11d94d46b25eae262a8a05a339631a2ff8ae169d68e840162105e29db0f90565b611c3a604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f27e7e8165e00d498bb1b43e931120d24a22f4d62bf3e60214827889b57bf91c3918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561420f5750600090506003614293565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614263573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661428c57600060019250925050614293565b9150600090505b94509492505050565b60008160048111156142b0576142b0614b61565b036142b85750565b60018160048111156142cc576142cc614b61565b036143195760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610ce6565b600281600481111561432d5761432d614b61565b0361437a5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610ce6565b600381600481111561438e5761438e614b61565b03610d0f5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610ce6565b82546000908190801561452c57600061440487612ea16001856151d6565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156144855760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610ce6565b805163ffffffff8088169116036144cd57846144a688612ea16001866151d6565b80546001600160e01b0392909216600160201b0263ffffffff90921691909117905561451c565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b60200151925083915061341c9050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b02919093161792019190915590508161341c565b600081831161459457816111e0565b5090919050565b600080608083901c156145b057608092831c92015b604083901c156145c257604092831c92015b602083901c156145d457602092831c92015b601083901c156145e657601092831c92015b600883901c156145f857600892831c92015b600483901c1561460a57600492831c92015b600283901c1561461c57600292831c92015b600183901c15610c9a5760010192915050565b600081831061459457816111e0565b600061464d60028484186153e8565b6111e09084841661522a565b60006020828403121561466b57600080fd5b81356001600160e01b0319811681146111e057600080fd5b60006020828403121561469557600080fd5b5035919050565b60005b838110156146b757818101518382015260200161469f565b50506000910152565b600081518084526146d881602086016020860161469c565b601f01601f19169290920160200192915050565b6020815260006111e060208301846146c0565b6001600160a01b0381168114610d0f57600080fd5b60006020828403121561472657600080fd5b81356111e0816146ff565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561476f5761476f614731565b604052919050565b60006001600160401b0382111561479057614790614731565b5060051b60200190565b600082601f8301126147ab57600080fd5b813560206147c06147bb83614777565b614747565b82815260059290921b840181019181810190868411156147df57600080fd5b8286015b84811015611ab85780356147f6816146ff565b83529183019183016147e3565b600082601f83011261481457600080fd5b813560206148246147bb83614777565b82815260059290921b8401810191818101908684111561484357600080fd5b8286015b84811015611ab85780358352918301918301614847565b60006001600160401b0382111561487757614877614731565b50601f01601f191660200190565b60006148936147bb8461485e565b90508281528383830111156148a757600080fd5b828260208301376000602084830101529392505050565b600082601f8301126148cf57600080fd5b6111e083833560208501614885565b600082601f8301126148ef57600080fd5b813560206148ff6147bb83614777565b82815260059290921b8401810191818101908684111561491e57600080fd5b8286015b84811015611ab85780356001600160401b038111156149415760008081fd5b61494f8986838b01016148be565b845250918301918301614922565b600080600080600060a0868803121561497557600080fd5b8535945060208601356001600160401b038082111561499357600080fd5b61499f89838a0161479a565b955060408801359150808211156149b557600080fd5b6149c189838a01614803565b945060608801359150808211156149d757600080fd5b6149e389838a016148de565b935060808801359150808211156149f957600080fd5b508601601f81018813614a0b57600080fd5b614a1a88823560208401614885565b9150509295509295909350565b600080600060608486031215614a3c57600080fd5b8335614a47816146ff565b95602085013595506040909401359392505050565b60008060008060808587031215614a7257600080fd5b8435614a7d816146ff565b93506020850135614a8d816146ff565b92506040850135915060608501356001600160401b03811115614aaf57600080fd5b614abb878288016148be565b91505092959194509250565b60008083601f840112614ad957600080fd5b5081356001600160401b03811115614af057600080fd5b602083019150836020828501011115614b0857600080fd5b9250929050565b60008060008060608587031215614b2557600080fd5b843593506020850135925060408501356001600160401b03811115614b4957600080fd5b614b5587828801614ac7565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b6020810160098310614b9957634e487b7160e01b600052602160045260246000fd5b91905290565b60008060008060808587031215614bb557600080fd5b84356001600160401b0380821115614bcc57600080fd5b614bd88883890161479a565b95506020870135915080821115614bee57600080fd5b614bfa88838901614803565b94506040870135915080821115614c1057600080fd5b50614c1d878288016148de565b949793965093946060013593505050565b600080600080600060a08688031215614c4657600080fd5b85356001600160401b0380821115614c5d57600080fd5b614c6989838a0161479a565b96506020880135915080821115614c7f57600080fd5b614c8b89838a01614803565b95506040880135915080821115614ca157600080fd5b50614cae888289016148de565b935050606086013591506080860135614cc6816146ff565b809150509295509295909350565b60008060408385031215614ce757600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015614d2657815187529582019590820190600101614d0a565b509495945050505050565b60ff60f81b8816815260e060208201526000614d5060e08301896146c0565b8281036040840152614d6281896146c0565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050614d938185614cf6565b9a9950505050505050505050565b600080600080600060a08688031215614db957600080fd5b8535614dc4816146ff565b94506020860135614dd4816146ff565b935060408601356001600160401b0380821115614df057600080fd5b614dfc89838a01614803565b94506060880135915080821115614e1257600080fd5b614e1e89838a01614803565b93506080880135915080821115614e3457600080fd5b50614a1a888289016148be565b803560ff8116811461187a57600080fd5b60008060008060008060a08789031215614e6b57600080fd5b8635955060208701359450614e8260408801614e41565b935060608701356001600160401b0380821115614e9e57600080fd5b614eaa8a838b01614ac7565b90955093506080890135915080821115614ec357600080fd5b50614ed089828a016148be565b9150509295509295509295565b60008060008060608587031215614ef357600080fd5b8435614efe816146ff565b93506020850135925060408501356001600160401b03811115614b4957600080fd5b600080600080600060808688031215614f3857600080fd5b8535945060208601359350614f4f60408701614e41565b925060608601356001600160401b03811115614f6a57600080fd5b614f7688828901614ac7565b969995985093965092949392505050565b60008060008060808587031215614f9d57600080fd5b8435614fa8816146ff565b9350602085013592506040850135915060608501356001600160401b03811115614aaf57600080fd5b600080600060608486031215614fe657600080fd5b8335925060208401359150614ffd60408501614e41565b90509250925092565b600080600080600060a0868803121561501e57600080fd5b8535615029816146ff565b94506020860135615039816146ff565b9350604086013592506060860135915060808601356001600160401b0381111561506257600080fd5b614a1a888289016148be565b60008060008060008060008060006101008a8c03121561508d57600080fd5b8935985060208a013597506150a460408b01614e41565b965060608a01356001600160401b03808211156150c057600080fd5b6150cc8d838e01614ac7565b909850965060808c01359150808211156150e557600080fd5b506150f28c828d016148be565b94505061510160a08b01614e41565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060c0878903121561513757600080fd5b863595506020870135945061514e60408801614e41565b935061515c60608801614e41565b92506080870135915060a087013590509295509295509295565b8183823760009101908152919050565b600181811c9082168061519a57607f821691505b6020821081036151ba57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c9a57610c9a6151c0565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b80820180821115610c9a57610c9a6151c0565b600081518084526020808501945080840160005b83811015614d265781516001600160a01b031687529582019590820190600101615251565b600081518084526020808501808196508360051b8101915082860160005b858110156152be5782840389526152ac8483516146c0565b98850198935090840190600101615294565b5091979650505050505050565b60006101208b8352602060018060a01b038c16818501528160408501526152f48285018c61523d565b91508382036060850152615308828b614cf6565b915083820360808501528189518084528284019150828160051b850101838c0160005b8381101561535957601f198784030185526153478383516146c0565b9486019492509085019060010161532b565b505086810360a088015261536d818c615276565b9450505050508560c08401528460e084015282810361010084015261539281856146c0565b9c9b505050505050505050505050565b6000602082840312156153b457600080fd5b5051919050565b8082028115828204841417610c9a57610c9a6151c0565b634e487b7160e01b600052601260045260246000fd5b6000826153f7576153f76153d2565b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561543d57600080fd5b81516111e0816146ff565b60006020828403121561545a57600080fd5b81516001600160401b0381111561547057600080fd5b8201601f8101841361548157600080fd5b805161548f6147bb8261485e565b8181528560208385010111156154a457600080fd5b6120a682602083016020860161469c565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156154dd57600080fd5b815165ffffffffffff811681146111e057600080fd5b60a08152600061550660a083018861523d565b82810360208401526155188188614cf6565b9050828103604084015261552c8187615276565b606084019590955250506001600160a01b03919091166080909101529392505050565b60006020828403121561556157600080fd5b8151600381106111e057600080fd5b60006080828403121561558257600080fd5b604051608081018181106001600160401b03821117156155a4576155a4614731565b6040528251815260208301516155b9816146ff565b6020820152604083810151908201526060928301519281019290925250919050565b6000600182016155ed576155ed6151c0565b5060010190565b6000825161560681846020870161469c565b9190910192915050565b84815260ff8416602082015282604082015260806060820152600061334160808301846146c0565b85815260ff8516602082015283604082015260a06060820152600061566060a08301856146c0565b8281036080840152611f5181856146c0565b65ffffffffffff828116828216039080821115615691576156916151c0565b5092915050565b600065ffffffffffff808416806156b1576156b16153d2565b92169190910492915050565b600080604083850312156156d057600080fd5b50508051602090910151909290915056fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a2646970667358221220129f3447433c59a981e767b2f1452563adddce84ada246938e565b4cf0250b8564736f6c63430008130033

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

000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f1100000000000000000000000050a459fc0069843750091d6382afc960d0b22b6d

-----Decoded View---------------
Arg [0] : _ve (address): 0xe0d35cf2ab00f3C11F10535DB27807F3DE139F11
Arg [1] : _voter (address): 0x50a459FC0069843750091D6382aFC960d0b22b6d

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e0d35cf2ab00f3c11f10535db27807f3de139f11
Arg [1] : 00000000000000000000000050a459fc0069843750091d6382afc960d0b22b6d


Deployed Bytecode Sourcemap

219994:4109:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;183683:37;219994:4109;;;;;183800:961;;;;;;;;;;-1:-1:-1;183800:961:0;;;;;:::i;:::-;;:::i;:::-;;;470:14:1;;463:22;445:41;;433:2;418:18;183800:961:0;;;;;;;;221411:112;;;;;;;;;;-1:-1:-1;221508:6:0;221411:112;;;643:25:1;;;631:2;616:18;221411:112:0;497:177:1;218343:152:0;;;;;;;;;;-1:-1:-1;218343:152:0;;;;;:::i;:::-;;:::i;184826:100::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;222033:207::-;;;;;;;;;;-1:-1:-1;222033:207:0;;;;;:::i;:::-;;:::i;189870:1732::-;;;;;;;;;;-1:-1:-1;189870:1732:0;;;;;:::i;:::-;;:::i;197006:234::-;;;;;;;;;;-1:-1:-1;197006:234:0;;;;;:::i;:::-;;:::i;204100:164::-;;;;;;;;;;-1:-1:-1;204100:164:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;8116:33:1;;;8098:52;;8086:2;8071:18;204100:164:0;7954:202:1;223232:136:0;;;;;;;;;;-1:-1:-1;223232:136:0;;;;;:::i;:::-;;:::i;212397:33::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8347:32:1;;;8329:51;;8317:2;8302:18;212397:33:0;8161:225:1;181354:68:0;;;;;;;;;;;;181409:13;181354:68;;187915:151;;;;;;;;;;-1:-1:-1;187915:151:0;;;;;:::i;:::-;187999:7;188026:22;;;:10;:22;;;;;:32;-1:-1:-1;;;;;188026:32:0;;187915:151;180567:148;;;;;;;;;;;;180627:88;180567:148;;202180:789;;;;;;;;;;-1:-1:-1;202180:789:0;;;;;:::i;:::-;;:::i;221292:111::-;;;;;;;;;;-1:-1:-1;221388:6:0;221292:111;;186501:1088;;;;;;;;;;-1:-1:-1;186501:1088:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;192592:627::-;;;;;;;;;;-1:-1:-1;192592:627:0;;;;;:::i;:::-;;:::i;220144:29::-;;;;;;;;;;;;;;;223769:331;;;;;;;;;;-1:-1:-1;223769:331:0;;;;;:::i;:::-;;:::i;213146:284::-;;;;;;;;;;;;;:::i;220302:52::-;;;;;;;;;;;;220351:3;220302:52;;181303:44;;;;;;;;;;;;;;;;206154:326;;;;;;;;;;-1:-1:-1;206154:326:0;;;;;:::i;:::-;206242:20;206351:26;;;:14;:26;;;;;206396:25;;206423:21;;;;206446:25;;;;;206396;;206154:326;;;;;11288:25:1;;;11344:2;11329:18;;11322:34;;;;11372:18;;;11365:34;11276:2;11261:18;206154:326:0;11086:319:1;184994:101:0;;;;;;;;;;-1:-1:-1;185077:10:0;;;;;;;;;;;;-1:-1:-1;;;185077:10:0;;;;184994:101;;221531:288;;;;;;;;;;-1:-1:-1;221531:288:0;;;;;:::i;:::-;;:::i;220206:26::-;;;;;;;;;;-1:-1:-1;220206:26:0;;;;-1:-1:-1;;;;;220206:26:0;;;216841:671;;;;;;;;;;-1:-1:-1;216841:671:0;;;;;:::i;:::-;;:::i;191670:855::-;;;;;;:::i;:::-;;:::i;223376:154::-;;;;;;;;;;;;;:::i;205908:169::-;;;;;;;;;;-1:-1:-1;205908:169:0;;;;;:::i;:::-;206001:4;206025:26;;;:14;:26;;;;;;;;:44;;;:35;;;;:44;;;;;;;;205908:169;220371:53;;;;;;;;;;;;220418:6;220371:53;;142918:657;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;220180:19::-;;;;;;;;;;-1:-1:-1;220180:19:0;;;;-1:-1:-1;;;;;220180:19:0;;;212725:260;;;;;;;;;;;;;:::i;:::-;;;14448:14:1;14436:27;;;14418:46;;14406:2;14391:18;212725:260:0;14274:196:1;215059:202:0;;;;;;;;;;-1:-1:-1;215059:202:0;;;;;:::i;:::-;;:::i;222947:210::-;;;;;;;;;;;;;:::i;217623:96::-;;;;;;;;;;-1:-1:-1;217708:3:0;217623:96;;220431:36;;;;;;;;;;;;;;;;220267:28;;;;;;;;;;-1:-1:-1;220267:28:0;;;;-1:-1:-1;;;;;220267:28:0;;;216530:193;;;;;;;;;;;;;:::i;186083:352::-;;;;;;;;;;-1:-1:-1;186083:352:0;;;;;:::i;:::-;;:::i;221827:198::-;;;;;;;;;;;;;:::i;222248:194::-;;;;;;;;;;;;;:::i;204658:255::-;;;;;;;;;;-1:-1:-1;204658:255:0;;;;;:::i;:::-;-1:-1:-1;;;204658:255:0;;;;;;;;198354:355;;;;;;;;;;-1:-1:-1;198354:355:0;;;;;:::i;:::-;;:::i;188143:149::-;;;;;;;;;;-1:-1:-1;188143:149:0;;;;;:::i;:::-;188227:7;188254:22;;;:10;:22;;;;;:30;;;-1:-1:-1;;;;;188254:30:0;;188143:149;203428:299;;;;;;:::i;:::-;;:::i;197958:308::-;;;;;;;;;;-1:-1:-1;197958:308:0;;;;;:::i;:::-;;:::i;197319:264::-;;;;;;;;;;-1:-1:-1;197319:264:0;;;;;:::i;:::-;;:::i;222739:200::-;;;;;;;;;;-1:-1:-1;222739:200:0;;;;;:::i;:::-;;:::i;220239:21::-;;;;;;;;;;-1:-1:-1;220239:21:0;;;;-1:-1:-1;;;;;220239:21:0;;;205705:138;;;;;;;;;;-1:-1:-1;205794:41:0;;;;;;;;;;;;;;;;;;205705:138;;197652:227;;;;;;;;;;-1:-1:-1;197652:227:0;;;;;:::i;:::-;;:::i;180465:95::-;;;;;;;;;;;;180507:53;180465:95;;181429:46;;;;;;;;;;;;;;;204345:227;;;;;;;;;;-1:-1:-1;204345:227:0;;;;;:::i;:::-;-1:-1:-1;;;204345:227:0;;;;;;;;217859:196;;;;;;;;;;-1:-1:-1;217859:196:0;;;;;:::i;:::-;;:::i;199352:846::-;;;;;;;;;;-1:-1:-1;199352:846:0;;;;;:::i;:::-;;:::i;198783:476::-;;;;;;;;;;-1:-1:-1;198783:476:0;;;;;:::i;:::-;;:::i;212361:29::-;;;;;;;;;;;;;;;183800:961;183902:4;-1:-1:-1;;;;;;184128:326:0;;-1:-1:-1;;;184128:326:0;;:506;;-1:-1:-1;;;;;;;184534:100:0;;-1:-1:-1;;;184534:100:0;184128:506;:572;;;-1:-1:-1;;;;;;;184651:49:0;;-1:-1:-1;;;184651:49:0;184128:572;:625;;;-1:-1:-1;;;;;;;;;;112792:40:0;;;184717:36;184108:645;183800:961;-1:-1:-1;;183800:961:0:o;218343:152::-;736:10;204008:4;182910:27;182902:64;;;;-1:-1:-1;;;182902:64:0;;21464:2:1;182902:64:0;;;21446:21:1;21503:2;21483:18;;;21476:30;-1:-1:-1;;;21522:18:1;;;21515:54;21586:18;;182902:64:0;;;;;;;;;182977:281;;183195:52;183232:11;183202:26;:15;:24;:26::i;:::-;:41;183195:52;;183011:247;182977:281;218445:42:::1;218468:18;218445:22;:42::i;:::-;218343:152:::0;:::o;184826:100::-;184880:13;184913:5;184906:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;184826:100;:::o;222033:207::-;-1:-1:-1;;;;;222096:26:0;;222092:52;;222131:13;;-1:-1:-1;;;222131:13:0;;;;;;;;;;;222092:52;222173:4;;-1:-1:-1;;;;;222173:4:0;222159:10;:18;222155:40;;222186:9;;-1:-1:-1;;;222186:9:0;;;;;;;;;;;222155:40;222206:11;:26;;-1:-1:-1;;;;;;222206:26:0;-1:-1:-1;;;;;222206:26:0;;;;;;;;;;222033:207::o;189870:1732::-;190093:7;736:10;190093:7;190182;:5;:7::i;:::-;190155:34;;;;190277:19;:17;:19::i;:::-;190224:49;190233:8;190243:7;190252:20;190271:1;190252:16;:20;:::i;190224:49::-;:72;;190202:171;;;;-1:-1:-1;;;190202:171:0;;22743:2:1;190202:171:0;;;22725:21:1;22782:2;22762:18;;;22755:30;22821:34;22801:18;;;22794:62;-1:-1:-1;;;22872:18:1;;;22865:47;22929:19;;190202:171:0;22541:413:1;190202:171:0;190386:18;190407:81;190420:7;190429:6;190437:9;190464:11;190448:29;;;;;;190479:8;190407:12;:81::i;:::-;190386:102;;190527:6;:13;190509:7;:14;:31;190501:77;;;;-1:-1:-1;;;190501:77:0;;;;;;;:::i;:::-;190615:9;:16;190597:7;:14;:34;190589:80;;;;-1:-1:-1;;;190589:80:0;;;;;;;:::i;:::-;190705:1;190688:7;:14;:18;190680:55;;;;-1:-1:-1;;;190680:55:0;;23563:2:1;190680:55:0;;;23545:21:1;23602:2;23582:18;;;23575:30;23641:26;23621:18;;;23614:54;23685:18;;190680:55:0;23361:348:1;190680:55:0;190797:1;190754:22;;;:10;:22;;;;;:31;-1:-1:-1;;;190754:31:0;;-1:-1:-1;;;;;190754:31:0;:45;190746:91;;;;-1:-1:-1;;;190746:91:0;;23916:2:1;190746:91:0;;;23898:21:1;23955:2;23935:18;;;23928:30;23994:34;23974:18;;;23967:62;-1:-1:-1;;;24045:18:1;;;24038:31;24086:19;;190746:91:0;23714:397:1;190746:91:0;190850:16;190869:32;221388:6;190869:16;:32;:::i;:::-;190850:51;-1:-1:-1;190912:16:0;190931:25;221508:6;190850:51;190931:25;:::i;:::-;190912:44;;190994:296;;;;;;;;191033:19;:8;:17;:19::i;:::-;-1:-1:-1;;;;;190994:296:0;;;-1:-1:-1;;;;;190994:296:0;;;;;;-1:-1:-1;190994:296:0;;;;;;191140:19;:8;:17;:19::i;:::-;-1:-1:-1;;;;;190994:296:0;;;;;191189:1;190994:296;;;;;;;;;;;;;;;;;;;;;;;;;;;;190969:22;;;:10;:22;;;;;;:321;;;;;;;;;;;;;;;-1:-1:-1;;;;;;190969:321:0;;;;;;;-1:-1:-1;;;;;;;;190969:321:0;;;;;;-1:-1:-1;;;;;190969:321:0;-1:-1:-1;;;190969:321:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;190969:321:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;190969:321:0;;;;;;-1:-1:-1;;190969:321:0;;;;;;;;;;;;;;-1:-1:-1;;190969:321:0;;;;;;;;;;;;;;;191442:14;;191308:256;;190969:22;;191363:8;;191442:14;;191408:6;;191429:28;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;191472:9;191496:8;191519;191542:11;191308:256;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;191584:10:0;;189870:1732;-1:-1:-1;;;;;;;;;189870:1732:0:o;197006:234::-;197149:7;197176:56;197186:7;197195;197204:9;197215:16;189785:9;;;;;;;;;-1:-1:-1;189785:9:0;;;189703:99;197215:16;197176:9;:56::i;:::-;197169:63;;197006:234;;;;;;:::o;204100:164::-;-1:-1:-1;;;204100:164:0;;;;;;;:::o;223232:136::-;223305:6;;-1:-1:-1;;;;;223305:6:0;223291:10;:20;223287:44;;223320:11;;-1:-1:-1;;;223320:11:0;;;;;;;;;;;223287:44;223342:18;223348:11;223342:5;:18::i;:::-;;223232:136;:::o;202180:789::-;202326:29;202358:22;;;:10;:22;;;;;202296:19;;202414:17;202369:10;202414:5;:17::i;:::-;202391:40;-1:-1:-1;202460:20:0;202450:6;:30;;;;;;;;:::i;:::-;;:65;;;-1:-1:-1;202494:21:0;202484:6;:31;;;;;;;;:::i;:::-;;202450:65;202442:109;;;;-1:-1:-1;;;202442:109:0;;27403:2:1;202442:109:0;;;27385:21:1;27442:2;27422:18;;;27415:30;27481:33;27461:18;;;27454:61;27532:18;;202442:109:0;27201:355:1;202442:109:0;202582:18;;-1:-1:-1;;;;;202582:18:0;736:10;202562:17;202669:46;736:10;202688:7;202582:18;202708:6;202669:9;:46::i;:::-;202652:63;;202726:21;202810:6;202790:16;;202751:6;-1:-1:-1;;;;;202751:25:0;;202777:9;202751:36;;;;;;;;;;;;;643:25:1;;631:2;616:18;;497:177;202751:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;;:::i;:::-;202750:66;;;;:::i;:::-;202726:90;;202844:13;202835:6;:22;202827:70;;;;-1:-1:-1;;;202827:70:0;;28382:2:1;202827:70:0;;;28364:21:1;28421:2;28401:18;;;28394:30;28460:34;28440:18;;;28433:62;-1:-1:-1;;;28511:18:1;;;28504:33;28554:19;;202827:70:0;28180:399:1;202827:70:0;202944:7;202935;-1:-1:-1;;;;;202915:46:0;202923:10;202915:46;202953:7;;202915:46;;;;;;;:::i;:::-;;;;;;;;202285:684;;;;;;;202180:789;;;;:::o;186501:1088::-;186574:13;186632:22;;;:10;:22;;;;;186671:17;;;;;;186667:79;;;-1:-1:-1;186712:22:0;;186501:1088;-1:-1:-1;;186501:1088:0:o;186667:79::-;186762:17;;;;;;;;;186758:79;;;-1:-1:-1;186803:22:0;;186501:1088;-1:-1:-1;;186501:1088:0:o;186758:79::-;186853:15;;;;;;;;;186849:75;;;-1:-1:-1;186892:20:0;;186501:1088;-1:-1:-1;;186501:1088:0:o;186849:75::-;186936:16;188026:22;;;:10;:22;;;;;:32;-1:-1:-1;;;;;188026:32:0;;187000:13;;;186996:85;;187030:39;;-1:-1:-1;;;187030:39:0;;29181:2:1;187030:39:0;;;29163:21:1;29220:2;29200:18;;;29193:30;29259:31;29239:18;;;29232:59;29308:18;;187030:39:0;28979:353:1;186996:85:0;187093:24;187120:7;:5;:7::i;:::-;187093:34;;;;187156:16;187144:8;:28;187140:89;;-1:-1:-1;187196:21:0;;186501:1088;-1:-1:-1;;;;186501:1088:0:o;187140:89::-;187241:16;188254:22;;;:10;:22;;;;;:30;;;-1:-1:-1;;;;;188254:30:0;187305:28;;;187301:88;;-1:-1:-1;187357:20:0;;186501:1088;-1:-1:-1;;;;;186501:1088:0:o;187301:88::-;187405:26;187420:10;187405:14;:26::i;:::-;:56;;;;-1:-1:-1;207053:4:0;207106:26;;;:14;:26;;;;;207176:25;;207152:21;;;;;:49;187435:26;187401:181;;;-1:-1:-1;187485:23:0;;186501:1088;-1:-1:-1;;;;;186501:1088:0:o;187401:181::-;-1:-1:-1;187548:22:0;;186501:1088;-1:-1:-1;;;;;186501:1088:0:o;192592:627::-;192786:7;736:10;192786:7;192869:67;192882:7;192891:6;192899:9;192910:15;736:10;192869:12;:67::i;:::-;192848:88;-1:-1:-1;192976:21:0;192955:17;192961:10;192955:5;:17::i;:::-;:42;;;;;;;;:::i;:::-;;192947:83;;;;-1:-1:-1;;;192947:83:0;;29539:2:1;192947:83:0;;;29521:21:1;29578:2;29558:18;;;29551:30;29617;29597:18;;;29590:58;29665:18;;192947:83:0;29337:352:1;192947:83:0;193061:22;;;;:10;:22;;;;;:31;-1:-1:-1;;;;;193049:43:0;;;-1:-1:-1;;;193061:31:0;;;;193049:43;193041:90;;;;-1:-1:-1;;;193041:90:0;;29896:2:1;193041:90:0;;;29878:21:1;29935:2;29915:18;;;29908:30;29974:34;29954:18;;;29947:62;-1:-1:-1;;;30025:18:1;;;30018:32;30067:19;;193041:90:0;29694:398:1;193041:90:0;193149:62;193157:7;193166:6;193174:9;193185:15;193202:8;193149:7;:62::i;:::-;193142:69;192592:627;-1:-1:-1;;;;;;;192592:627:0:o;223769:331::-;181409:13;223849:17;:39;223845:77;;;223897:25;;-1:-1:-1;;;223897:25:0;;;;;;;;;;;223845:77;223951:5;-1:-1:-1;;;;;223951:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;223937:30:0;:10;-1:-1:-1;;;;;223937:30:0;;223933:56;;223976:13;;-1:-1:-1;;;223976:13:0;;;;;;;;;;;223933:56;224000:16;:36;;;224054:38;;643:25:1;;;224054:38:0;;631:2:1;616:18;224054:38:0;;;;;;;223769:331;:::o;213146:284::-;213206:13;213253:5;-1:-1:-1;;;;;213236:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;213236:37:0;;;;;;;;;;;;:::i;:::-;;;213232:191;;-1:-1:-1;213373:38:0;;;;;;;;;;;;;;;;;;213146:284::o;213232:191::-;213330:9;213146:284;-1:-1:-1;213146:284:0:o;221531:288::-;221618:4;;-1:-1:-1;;;;;221618:4:0;221604:10;:18;221600:40;;221631:9;;-1:-1:-1;;;221631:9:0;;;;;;;;;;;221600:40;220351:3;221655:9;:34;221651:73;;;221698:26;;-1:-1:-1;;;221698:26:0;;;;;;;;;;;221651:73;221735:17;:29;;;221780:31;;221755:9;;221780:31;;;;;221531:288;:::o;216841:671::-;217008:23;:43;216914:7;;217066:11;;;217062:67;;-1:-1:-1;;217101:16:0;;;216841:671;-1:-1:-1;216841:671:0:o;217062:67::-;217200:39;217242:23;217279:10;217288:1;217279:6;:10;:::i;:::-;217242:48;;;;;;;;:::i;:::-;;;;;;;;;;217200:90;;;;;;;;;217242:48;;217200:90;;;;;;;-1:-1:-1;;;217200:90:0;;;-1:-1:-1;;;;;217200:90:0;;;;;;;;;-1:-1:-1;;;217301:77:0;;217353:13;;;-1:-1:-1;;;;;217346:20:0;;216841:671;-1:-1:-1;;;216841:671:0:o;217301:77::-;217441:63;217483:20;:9;:18;:20::i;:::-;217441:23;;:41;:63::i;:::-;-1:-1:-1;;;;;217434:70:0;;216841:671;-1:-1:-1;;;;216841:671:0:o;191670:855::-;191900:7;191920:18;191941:67;191954:7;191963:6;191971:9;191982:15;191999:8;191941:12;:67::i;:::-;191920:88;;192021:20;192044:17;192050:10;192044:5;:17::i;:::-;192021:40;-1:-1:-1;192090:23:0;192080:6;:33;;;;;;;;:::i;:::-;;192072:79;;;;-1:-1:-1;;;192072:79:0;;31340:2:1;192072:79:0;;;31322:21:1;31379:2;31359:18;;;31352:30;31418:34;31398:18;;;31391:62;-1:-1:-1;;;31469:18:1;;;31462:31;31510:19;;192072:79:0;31138:397:1;192072:79:0;192162:22;;;;:10;:22;;;;;;;:31;;:38;;-1:-1:-1;;192162:38:0;192196:4;192162:38;;;192218:28;;;;;192173:10;643:25:1;;631:2;616:18;;497:177;192218:28:0;;;;;;;;192259:71;192274:10;192286:7;192295:6;192303:9;192314:15;192259:14;:71::i;:::-;192341:65;192350:10;192362:7;192371:6;192379:9;192390:15;192341:8;:65::i;:::-;192417:70;192431:10;192443:7;192452:6;192460:9;192471:15;192417:13;:70::i;:::-;-1:-1:-1;192507:10:0;191670:855;-1:-1:-1;;;;;;191670:855:0:o;223376:154::-;223440:6;;-1:-1:-1;;;;;223440:6:0;223426:10;:20;223422:44;;223455:11;;-1:-1:-1;;;223455:11:0;;;;;;;;;;;223422:44;223484:6;223477:13;;-1:-1:-1;;;;;;223477:13:0;;;223506:16;;;;223484:6;;223506:16;223376:154::o;142918:657::-;143039:13;143067:18;;143039:13;;;143067:18;143341:41;:5;143039:13;143341:26;:41::i;:::-;143397:47;:8;143427:16;143397:29;:47::i;:::-;143540:16;;;143523:1;143540:16;;;;;;;;;-1:-1:-1;;;143288:279:0;;;-1:-1:-1;143288:279:0;;-1:-1:-1;143459:13:0;;-1:-1:-1;143495:4:0;;-1:-1:-1;143523:1:0;-1:-1:-1;143540:16:0;-1:-1:-1;143288:279:0;-1:-1:-1;142918:657:0:o;212725:260::-;212780:6;212820:5;-1:-1:-1;;;;;212803:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;212803:32:0;;;;;;;;-1:-1:-1;;212803:32:0;;;;;;;;;;;;:::i;:::-;;;212799:179;;212935:31;212953:12;212935:17;:31::i;:::-;212928:38;;212725:260;:::o;215059:202::-;215174:19;;-1:-1:-1;;;215174:19:0;;;;;643:25:1;;;215136:7:0;;;;-1:-1:-1;;;;;215174:2:0;:10;;;;616:18:1;;215174:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;215156:37;;215211:42;215221:7;215230;215239:9;215211:42;;;;;;;;;;;;:9;:42::i;222947:210::-;223009:13;;-1:-1:-1;;;;;223009:13:0;222995:10;:27;222991:58;;223031:18;;-1:-1:-1;;;223031:18:0;;;;;;;;;;;222991:58;223069:13;;;223060:6;:22;;-1:-1:-1;;;;;223069:13:0;;-1:-1:-1;;;;;;223060:22:0;;;;;;;;223093:20;;;;;;223129;;;;-1:-1:-1;;223129:20:0;222947:210::o;216530:193::-;216613:23;:43;216586:7;;216613:48;:102;;216683:32;:23;:30;:32::i;:::-;-1:-1:-1;;;;;216613:102:0;212928:38;;212725:260;:::o;216613:102::-;-1:-1:-1;216664:16:0;;;216530:193::o;186083:352::-;186315:7;186371;186380:6;186388:9;186399:15;186416:8;186360:65;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;186360:65:0;;;;;;;;;186350:76;;186360:65;186350:76;;;;;186083:352;-1:-1:-1;;;;;;186083:352:0:o;221827:198::-;221900:7;220418:6;221976:17;;221928:5;-1:-1:-1;;;;;221928:24:0;;221971:1;221953:15;:19;;;;:::i;:::-;221928:45;;;;;;;;;;;;;643:25:1;;631:2;616:18;;497:177;221928:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:65;;;;:::i;:::-;221927:90;;;;:::i;222248:194::-;222308:11;;-1:-1:-1;;;;;222308:11:0;222294:10;:25;222290:54;;222328:16;;-1:-1:-1;;;222328:16:0;;;;;;;;;;;222290:54;222362:11;;;222355:4;:18;;-1:-1:-1;;;;;222362:11:0;;-1:-1:-1;;;;;;222355:18:0;;;;;;;;222384;;;;;;222418:16;;;;-1:-1:-1;;222418:16:0;222248:194::o;198354:355::-;198573:7;;736:10;198593:28;;198639:62;198649:10;198661:5;198668:7;198677;198686:6;;198639:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;198694:6:0;;-1:-1:-1;198639:9:0;;-1:-1:-1;;198639:62:0:i;:::-;198632:69;198354:355;-1:-1:-1;;;;;;;;198354:355:0:o;203428:299::-;736:10;204008:4;182910:27;182902:64;;;;-1:-1:-1;;;182902:64:0;;21464:2:1;182902:64:0;;;21446:21:1;21503:2;21483:18;;;21476:30;-1:-1:-1;;;21522:18:1;;;21515:54;21586:18;;182902:64:0;21262:348:1;182902:64:0;182977:281;;183195:52;183232:11;183202:26;:15;:24;:26::i;:::-;:41;183195:52;;183011:247;182977:281;203547:12:::1;203561:23:::0;203588:6:::1;-1:-1:-1::0;;;;;203588:11:0::1;203607:5;203614:4;;203588:31;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;203546:73;;;;203630:89;203655:7;203664:10;203630:89;;;;;;;;;;;;;;;;;:24;:89::i;:::-;;203535:192;;203428:299:::0;;;;:::o;197958:308::-;198138:7;;736:10;198158:28;;198204:54;198214:10;198226:5;198233:7;198242;198251:6;;198204:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;198204:9:0;;-1:-1:-1;;;198204:54:0:i;197319:264::-;197502:7;197529:46;197539:7;197548;197557:9;197568:6;197529:9;:46::i;:::-;197522:53;197319:264;-1:-1:-1;;;;;197319:264:0:o;222739:200::-;222813:6;;-1:-1:-1;;;;;222813:6:0;222799:10;:20;222795:44;;222828:11;;-1:-1:-1;;;222828:11:0;;;;;;;;;;;222795:44;-1:-1:-1;;;;;222854:21:0;;222850:47;;222884:13;;-1:-1:-1;;;222884:13:0;;;;;;;;;;;222850:47;222908:13;:23;;-1:-1:-1;;;;;;222908:23:0;-1:-1:-1;;;;;222908:23:0;;;;;;;;;;222739:200::o;197652:227::-;197755:7;;736:10;197775:28;;197821:50;197831:10;197843:5;197850:7;197859;197821:50;;;;;;;;;;;;:9;:50::i;217859:196::-;217932:7;217708:3;217998:26;218014:9;217998:15;:26::i;:::-;217960:35;;-1:-1:-1;;;217960:35:0;;;;;643:25:1;;;217960:5:0;-1:-1:-1;;;;;217960:24:0;;;;616:18:1;;217960:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;;;;:::i;:::-;217959:88;;;;:::i;199352:846::-;199634:7;199654:13;199670:438;199698:351;180627:88;199853:10;199890:7;199940:6;;199924:24;;;;;;;:::i;:::-;;;;;;;;199985:6;199975:17;;;;;;199765:250;;;;;;;;;;;32945:25:1;;;33001:2;32986:18;;32979:34;;;;33061:4;33049:17;;;;33044:2;33029:18;;33022:45;33098:2;33083:18;;33076:34;33141:3;33126:19;;33119:35;32932:3;32917:19;;32690:470;199765:250:0;;;;;;;;;;;;;199733:301;;;;;;199698:16;:351::i;:::-;200064:1;200080;200096;199670:13;:438::i;:::-;199654:454;;200128:62;200138:10;200150:5;200157:7;200166;200175:6;;200128:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;200183:6:0;;-1:-1:-1;200128:9:0;;-1:-1:-1;;200128:62:0:i;:::-;200121:69;199352:846;-1:-1:-1;;;;;;;;;;;199352:846:0:o;198783:476::-;199074:48;;;180507:53;199074:48;;;33363:25:1;33404:18;;;33397:34;;;33479:4;33467:17;;33447:18;;;33440:45;198983:7:0;;;;199019:164;;199047:77;;33336:18:1;;199074:48:0;33165:326:1;199019:164:0;199003:180;;199201:50;199211:10;199223:5;199230:7;199239;199201:50;;;;;;;;;;;;:9;:50::i;108216:332::-;108280:13;108310:12;108316:5;110883:12;;;;;-1:-1:-1;;;110869:10:0;;;;;:26;;;110779:124;108310:12;108306:32;;;108331:7;;-1:-1:-1;;;108331:7:0;;;;;;;;;;;108306:32;-1:-1:-1;108369:12:0;;;;108349:17;108400:23;;;108369:12;108400:11;;;:23;;;;;;;108434:30;;;108500:29;;-1:-1:-1;;108500:29:0;108515:14;;-1:-1:-1;;;;;108500:29:0;;;;;;;;108400:23;108216:332::o;218727:925::-;217708:3;218837:18;:41;;218815:158;;;;-1:-1:-1;;;218815:158:0;;33698:2:1;218815:158:0;;;33680:21:1;33737:2;33717:18;;;33710:30;33776:34;33756:18;;;33749:62;33847:34;33827:18;;;33820:62;-1:-1:-1;;;33898:19:1;;;33891:34;33942:19;;218815:158:0;33496:471:1;218815:158:0;218986:26;219015:17;:15;:17::i;:::-;218986:46;-1:-1:-1;219169:23:0;;;;;:75;;-1:-1:-1;219196:23:0;:43;:48;219169:75;219165:259;;;219321:76;;;;;;;;;219261:36;219321:76;;219261:23;;219321:76;;;219365:30;:18;:28;:30::i;:::-;-1:-1:-1;;;;;219321:76:0;;;;;;219261:151;;;;;;;-1:-1:-1;219261:151:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;219261:151:0;;;;;;;;;;;;219165:259;219484:80;219513:18;:7;:5;:7::i;:::-;:16;;;:18::i;:::-;219533:30;:18;:28;:30::i;:::-;219484:23;;:80;:28;:80::i;:::-;-1:-1:-1;;219582:62:0;;;34146:25:1;;;34202:2;34187:18;;34180:34;;;219582:62:0;;34119:18:1;219582:62:0;;;;;;;218804:848;218727:925;:::o;28544:190::-;28600:6;-1:-1:-1;;;;;28627:25:0;;;28619:76;;;;-1:-1:-1;;;28619:76:0;;34427:2:1;28619:76:0;;;34409:21:1;34466:2;34446:18;;;34439:30;34505:34;34485:18;;;34478:62;-1:-1:-1;;;34556:18:1;;;34549:36;34602:19;;28619:76:0;34225:402:1;28619:76:0;-1:-1:-1;28720:5:0;28544:190::o;213560:1491::-;213798:22;;-1:-1:-1;;;213798:22:0;;;;;643:25:1;;;213740:7:0;;;;-1:-1:-1;;;;;213798:2:0;:13;;;;616:18:1;;213798:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;213760:60;-1:-1:-1;213853:32:0;213839:10;:46;;;;;;;;:::i;:::-;;213831:92;;;;-1:-1:-1;;;213831:92:0;;35114:2:1;213831:92:0;;;35096:21:1;35153:2;35133:18;;;35126:30;35192:34;35172:18;;;35165:62;-1:-1:-1;;;35243:18:1;;;35236:31;35284:19;;213831:92:0;34912:397:1;213831:92:0;213954:31;213940:10;:45;;;;;;;;:::i;:::-;;213936:132;;214009:47;;-1:-1:-1;;;214009:47:0;;-1:-1:-1;;;;;35534:32:1;;;214009:47:0;;;35516:51:1;35583:18;;;35576:34;;;35626:18;;;35619:34;;;214009:5:0;:18;;;;35489::1;;214009:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;214002:54;;;;;213936:132;214188:23;;-1:-1:-1;;;214188:23:0;;;;;643:25:1;;;214169:16:0;;214188:2;-1:-1:-1;;;;;214188:14:0;;;;616:18:1;;214188:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;214169:42;-1:-1:-1;214222:12:0;214237:46;-1:-1:-1;;;;;214237:2:0;:25;214169:42;214273:9;214237:25;:46::i;:::-;214314:31;;-1:-1:-1;;;214314:31:0;;;;;35836:25:1;;;35909:14;35897:27;;35877:18;;;35870:55;214222:61:0;;-1:-1:-1;214294:17:0;;-1:-1:-1;;;;;214314:2:0;:14;;;;35809:18:1;;214314:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;214294:61;;214370:9;214383:1;214370:14;214366:507;;214579:47;;-1:-1:-1;;;214579:47:0;;-1:-1:-1;;;;;35534:32:1;;;214579:47:0;;;35516:51:1;35583:18;;;35576:34;;;35626:18;;;35619:34;;;214552:24:0;;214579:5;:18;;;;;;35489::1;;214579:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;214658:29;;-1:-1:-1;;;214658:29:0;;;;;34146:25:1;;;34187:18;;;34180:34;;;214552:74:0;;-1:-1:-1;214641:14:0;;-1:-1:-1;;;;;214658:2:0;:10;;;;34119:18:1;;214658:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;214641:46;-1:-1:-1;214728:15:0;214746:39;-1:-1:-1;;;;;214746:2:0;:9;214756:8;214766:7;214775:9;214746;:39::i;:::-;214728:57;-1:-1:-1;214845:16:0;214826;214728:57;214826:6;:16;:::i;:::-;:35;;;;:::i;:::-;214819:42;;;;;;;;;;;214366:507;214996:47;;-1:-1:-1;;;214996:47:0;;-1:-1:-1;;;;;35534:32:1;;;214996:47:0;;;35516:51:1;35583:18;;;35576:34;;;35626:18;;;35619:34;;;214996:5:0;:18;;;;35489::1;;214996:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;214989:54;213560:1491;-1:-1:-1;;;;;;;;;213560:1491:0:o;195334:522::-;195387:7;195407:20;195430:17;195436:10;195430:5;:17::i;:::-;195407:40;-1:-1:-1;195492:20:0;195482:6;:30;;;;;;;;:::i;:::-;;;:83;;;;-1:-1:-1;195543:22:0;195533:6;:32;;;;;;;;:::i;:::-;;;195482:83;:135;;;;-1:-1:-1;195596:21:0;195586:6;:31;;;;;;;;:::i;:::-;;;195482:135;:188;;;;-1:-1:-1;195648:22:0;195638:6;:32;;;;;;;;:::i;:::-;;;195482:188;195460:267;;;;-1:-1:-1;;;195460:267:0;;36834:2:1;195460:267:0;;;36816:21:1;36873:2;36853:18;;;36846:30;36912:31;36892:18;;;36885:59;36961:18;;195460:267:0;36632:353:1;195460:267:0;195738:22;;;;:10;:22;;;;;;;:29;;:36;;-1:-1:-1;;195738:36:0;;;;;195792:26;;;;;195749:10;643:25:1;;631:2;616:18;;497:177;195792:26:0;;;;;;;;-1:-1:-1;195838:10:0;;195334:522;-1:-1:-1;195334:522:0:o;206550:280::-;206634:4;206687:26;;;:14;:26;;;;;206797:25;;;;206773:21;;;;:49;;206797:25;206773:49;:::i;:::-;187999:7;188026:22;;;:10;:22;;;;;:32;206733:36;;-1:-1:-1;;;;;188026:32:0;217859:196;:::i;206733:36::-;:89;;;206550:280;-1:-1:-1;;;206550:280:0:o;196148:789::-;196363:7;196383:18;196404:67;196417:7;196426:6;196434:9;196445:15;196462:8;196404:12;:67::i;:::-;196383:88;;196484:20;196507:17;196513:10;196507:5;:17::i;:::-;196484:40;-1:-1:-1;196569:20:0;196559:6;:30;;;;;;;;:::i;:::-;;;:83;;;;-1:-1:-1;196620:22:0;196610:6;:32;;;;;;;;:::i;:::-;;;196559:83;:135;;;;-1:-1:-1;196673:21:0;196663:6;:31;;;;;;;;:::i;:::-;;;196559:135;:188;;;;-1:-1:-1;196725:22:0;196715:6;:32;;;;;;;;:::i;:::-;;;196559:188;196537:267;;;;-1:-1:-1;;;196537:267:0;;36834:2:1;196537:267:0;;;36816:21:1;36873:2;36853:18;;;36846:30;36912:31;36892:18;;;36885:59;36961:18;;196537:267:0;36632:353:1;196537:267:0;196815:22;;;;:10;:22;;;;;;;:31;;:38;;-1:-1:-1;;196815:38:0;;;;;196871:28;;;;;196826:10;643:25:1;;631:2;616:18;;497:177;196871:28:0;;;;;;;;-1:-1:-1;196919:10:0;196148:789;-1:-1:-1;;;;;;196148:789:0:o;30660:190::-;30716:6;30752:16;30743:25;;;30735:76;;;;-1:-1:-1;;;30735:76:0;;37192:2:1;30735:76:0;;;37174:21:1;37231:2;37211:18;;;37204:30;37270:34;37250:18;;;37243:62;-1:-1:-1;;;37321:18:1;;;37314:36;37367:19;;30735:76:0;36990:402:1;84111:624:0;84230:24;;84196:7;;;84230:24;84334:1;84328:7;;84324:241;;;84352:11;84372:14;84382:3;84372:9;:14::i;:::-;84366:20;;:3;:20;:::i;:::-;88727:28;88792:20;;;88858:4;88845:18;;84352:34;;-1:-1:-1;88841:28:0;;84411:42;;;;;84405:48;;;;84401:153;;;84481:3;84474:10;;84401:153;;;84531:7;:3;84537:1;84531:7;:::i;:::-;84525:13;;84401:153;84337:228;84324:241;84577:11;84591:53;84610:4;84629:3;84634;84639:4;84591:18;:53::i;:::-;84577:67;-1:-1:-1;84664:8:0;;:63;;84679:41;84693:4;84712:7;84718:1;84712:3;:7;:::i;:::-;88727:28;88792:20;;;88858:4;88845:18;;;88841:28;;88614:273;84679:41;:48;-1:-1:-1;;;84679:48:0;;-1:-1:-1;;;;;84679:48:0;84664:63;;;84675:1;84657:70;84111:624;-1:-1:-1;;;;;;;84111:624:0:o;194013:553::-;194255:304;;194351:197;194375:7;194371:1;:11;194351:197;;;194434:4;-1:-1:-1;;;;;194412:27:0;:7;194420:1;194412:10;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;194412:27:0;;194408:125;;194464:49;194499:9;194509:1;194499:12;;;;;;;;:::i;:::-;;;;;;;194489:23;;;;;;194464:15;:24;;:49;;;;:::i;:::-;194384:3;;;:::i;:::-;;;194351:197;;194255:304;194013:553;;;;;:::o;193349:589::-;193579:26;:70;;;;;;;;;;;;;;;;;193678:14;;193579:70;;-1:-1:-1;193660:15:0;193703:228;193727:7;193723:1;:11;193703:228;;;193757:12;193771:23;193798:7;193806:1;193798:10;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;193798:15:0;193821:6;193828:1;193821:9;;;;;;;;:::i;:::-;;;;;;;193832;193842:1;193832:12;;;;;;;;:::i;:::-;;;;;;;193798:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;193756:89;;;;193860:59;193885:7;193894:10;193906:12;193860:24;:59::i;:::-;;193741:190;;193736:3;;;;:::i;:::-;;;193703:228;;;;193568:370;;193349:589;;;;;:::o;65836:244::-;65930:13;65238:4;65202:40;;65960:17;65956:117;;66001:15;66010:5;66001:8;:15::i;:::-;65994:22;;;;65956:117;66056:5;66049:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29602:190;29658:6;29694:16;29685:25;;;29677:76;;;;-1:-1:-1;;;29677:76:0;;38031:2:1;29677:76:0;;;38013:21:1;38070:2;38050:18;;;38043:30;38109:34;38089:18;;;38082:62;-1:-1:-1;;;38160:18:1;;;38153:36;38206:19;;29677:76:0;37829:402:1;84860:209:0;84956:24;;84922:7;;84998:8;;:63;;85013:41;85027:4;85046:7;85052:1;85046:3;:7;:::i;85013:41::-;:48;-1:-1:-1;;;85013:48:0;;-1:-1:-1;;;;;85013:48:0;84998:63;;;85009:1;84991:70;84860:209;-1:-1:-1;;;84860:209:0:o;201118:828::-;201336:7;201388:22;;;:10;:22;;;;;201450:20;201429:17;201435:10;201429:5;:17::i;:::-;:41;;;;;;;;:::i;:::-;;201421:89;;;;-1:-1:-1;;;201421:89:0;;38438:2:1;201421:89:0;;;38420:21:1;38477:2;38457:18;;;38450:30;38516:34;38496:18;;;38489:62;-1:-1:-1;;;38567:18:1;;;38560:33;38610:19;;201421:89:0;38236:399:1;201421:89:0;201568:18;;201523:14;;201540:55;;201550:7;;201559;;-1:-1:-1;;;;;201568:18:0;201588:6;201540:9;:55::i;:::-;201523:72;;201606:56;201617:10;201629:7;201638;201647:6;201655;201606:10;:56::i;:::-;201679:6;:13;201696:1;201679:18;201675:238;;201737:7;201728;-1:-1:-1;;;;;201719:63:0;;201746:10;201758:7;201767:6;201775;201719:63;;;;;;;;;:::i;:::-;;;;;;;;201675:238;;;201848:7;201839;-1:-1:-1;;;;;201820:81:0;;201857:10;201869:7;201878:6;201886;201894;201820:81;;;;;;;;;;:::i;:::-;;;;;;;;201932:6;201118:828;-1:-1:-1;;;;;;;;201118:828:0:o;104025:305::-;104175:12;104204:7;104200:123;;;-1:-1:-1;104235:10:0;104228:17;;104200:123;104278:33;104286:10;104298:12;104278:7;:33::i;200523:297::-;200711:7;200738:74;200748:10;200760:7;200769;200778;200787:6;200795:16;189785:9;;;;;;;;;-1:-1:-1;189785:9:0;;;189703:99;200795:16;200738:9;:74::i;:::-;200731:81;200523:297;-1:-1:-1;;;;;;200523:297:0:o;142696:167::-;142773:7;142800:55;142822:20;:18;:20::i;:::-;142844:10;137245:4;137239:11;-1:-1:-1;;;137264:23:0;;137317:4;137308:14;;137301:39;;;;137370:4;137361:14;;137354:34;137425:4;137410:20;;;137042:406;135258:236;135343:7;135364:17;135383:18;135405:25;135416:4;135422:1;135425;135428;135405:10;:25::i;:::-;135363:67;;;;135441:18;135453:5;135441:11;:18::i;:::-;-1:-1:-1;135477:9:0;135258:236;-1:-1:-1;;;;;135258:236:0:o;17824:195::-;17881:7;-1:-1:-1;;;;;17909:26:0;;;17901:78;;;;-1:-1:-1;;;17901:78:0;;39898:2:1;17901:78:0;;;39880:21:1;39937:2;39917:18;;;39910:30;39976:34;39956:18;;;39949:62;-1:-1:-1;;;40027:18:1;;;40020:37;40074:19;;17901:78:0;39696:403:1;82795:164:0;82877:7;;82913:38;82921:4;82940:3;82945:5;82913:7;:38::i;:::-;82906:45;;;;82795:164;;;;;;;:::o;208586:1105::-;208771:27;;-1:-1:-1;;;208771:27:0;;;;;643:25:1;;;208730:6:0;;;;-1:-1:-1;;;;;208771:17:0;;;;;616:18:1;;208771:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;208749:49;;208813:12;:17;;208829:1;208813:17;208809:31;;208839:1;208832:8;;;;;208809:31;208959:9;-1:-1:-1;;;;;208899:14:0;;;208914:8;208924:16;208939:1;208924:12;:16;:::i;:::-;208899:42;;-1:-1:-1;;;;;;208899:42:0;;;;;;;;;;35836:25:1;;;;35909:14;35897:27;35877:18;;;35870:55;35809:18;;208899:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:56;:69;208895:100;;208978:16;208993:1;208978:12;:16;:::i;:::-;208970:25;;;;;208895:100;209055:27;;-1:-1:-1;;;209055:27:0;;;;;35836:25:1;;;209080:1:0;35877:18:1;;;35870:55;209099:9:0;;-1:-1:-1;;;;;209055:14:0;;;;;35809:18:1;;209055:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;:53;209051:67;;;209117:1;209110:8;;;;;209051:67;209131:12;;209173:16;209188:1;209173:12;:16;:::i;:::-;209158:31;;209200:34;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;209200:34:0;209260:5;209252:13;;:5;:13;;;209245:416;;;209282:13;209324:1;209307:13;209315:5;209307;:13;:::i;:::-;209306:19;;;;:::i;:::-;209298:27;;:5;:27;:::i;:::-;209372:32;;-1:-1:-1;;;209372:32:0;;;;;35836:25:1;;;35909:14;35897:27;;35877:18;;;35870:55;209282:43:0;;-1:-1:-1;;;;;;209372:14:0;;;;;35809:18:1;;209372:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;209367:37;;209443:9;209423:2;:16;;;:29;209419:231;;209480:6;-1:-1:-1;209473:13:0;;-1:-1:-1;;;;209473:13:0;209419:231;209512:16;;:28;-1:-1:-1;209508:142:0;;;209569:6;209561:14;;209508:142;;;209624:10;209633:1;209624:6;:10;:::i;:::-;209616:18;;209508:142;209267:394;209245:416;;;-1:-1:-1;209678:5:0;;208586:1105;-1:-1:-1;;;;;;208586:1105:0:o;210175:1879::-;210371:28;;-1:-1:-1;;;210371:28:0;;;;;643:25:1;;;210329:7:0;;;;-1:-1:-1;;;;;210371:18:0;;;;;616::1;;210371:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;210415:27;;-1:-1:-1;;;210415:27:0;;;;;643:25:1;;;210349:51:0;;-1:-1:-1;;;;;;210415:18:0;;;;;616::1;;210415:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;210446:1;210415:32;210411:73;;210471:1;210464:8;;;;;210411:73;210496:20;210519:2;-1:-1:-1;;;;;210519:8:0;;:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;210648:35;;-1:-1:-1;;;210648:35:0;;-1:-1:-1;;;;;40961:32:1;;;210648:35:0;;;40943:51:1;41010:18;;;41003:34;;;210496:33:0;;-1:-1:-1;210540:14:0;;210587:1;;210540:14;;210617:67;;210648:12;;;;;;40916:18:1;;210648:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;56154:6;56360:16;;56347:30;;;56233:163;210617:67;210760:42;;-1:-1:-1;;;210760:42:0;;;;;34146:25:1;;;34187:18;;;34180:34;;;210599:85:0;;-1:-1:-1;210743:14:0;;-1:-1:-1;;;;;210760:24:0;;;;;34119:18:1;;210760:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;210853:32;;-1:-1:-1;;;210853:32:0;;;;;34146:25:1;;;34187:18;;;34180:34;;;210743:59:0;;-1:-1:-1;210814:13:0;;;;-1:-1:-1;;;;;210853:15:0;;;;;34119:18:1;;210853:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;210813:72;;-1:-1:-1;210813:72:0;-1:-1:-1;210980:56:0;210989:7;56154:6;56360:16;;56347:30;;210980:8;:56::i;:::-;210970:66;-1:-1:-1;211154:17:0;208367:6;211175:50;210970:66;56595:16;;;56582:30;;:37;;211175:50;:::i;:::-;211174:63;;;;:::i;:::-;211154:83;-1:-1:-1;211248:20:0;211285:13;;211281:740;;211320:9;211315:695;211339:9;211335:1;:13;211315:695;;;-1:-1:-1;;;;;211446:24:0;;;211471:7;211501:1;211480:18;208367:6;211480:7;:18;:::i;:::-;:22;;;;:::i;:::-;211446:57;;-1:-1:-1;;;;;;211446:57:0;;;;;;;;;;34146:25:1;;;;34187:18;;;34180:34;34119:18;;211446:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;211437:66;;211595:3;-1:-1:-1;;;;;211595:15:0;;211611:7;211620:6;211595:32;;;;;;;;;;;;;;;34146:25:1;;;34202:2;34187:18;;34180:34;34134:2;34119:18;;33972:248;211595:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;211571:56;;-1:-1:-1;211571:56:0;-1:-1:-1;;;;;;211729:21:0;;;;211751:23;211796:1;211775:18;208367:6;211775:7;:18;:::i;:::-;:22;;;;:::i;:::-;211751:47;;;;;;;;;;;;;643:25:1;;631:2;616:18;;497:177;211751:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;211729:70;;;;;;;;;;;;;643:25:1;;631:2;616:18;;497:177;211729:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;211710:89;-1:-1:-1;211828:25:0;;-1:-1:-1;211710:89:0;211851:1;211828:8;:25::i;:::-;211898:47;;-1:-1:-1;;;211898:47:0;;-1:-1:-1;;;;;40961:32:1;;;211898:47:0;;;40943:51:1;41010:18;;;41003:34;;;211818:35:0;;-1:-1:-1;211818:35:0;;211898:24;;;;;40916:18:1;;211898:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;211883:62;;:12;:62;:::i;:::-;211882:74;;;;:::i;:::-;211872:84;;;;:::i;:::-;;-1:-1:-1;211975:19:0;208367:6;211975:19;;:::i;:::-;;-1:-1:-1;211350:3:0;;;;:::i;:::-;;;;211315:695;;;;211281:740;-1:-1:-1;212040:6:0;;210175:1879;-1:-1:-1;;;;;;;;;;;;;210175:1879:0:o;7220:1673::-;7268:7;7292:1;7297;7292:6;7288:47;;-1:-1:-1;7322:1:0;;7220:1673;-1:-1:-1;7220:1673:0:o;7288:47::-;8026:14;8060:1;8049:7;8054:1;8049:4;:7::i;:::-;:12;;8043:1;:19;;8026:36;;8528:1;8517:6;8513:1;:10;;;;;:::i;:::-;;8504:6;:19;8503:26;;8494:35;;8578:1;8567:6;8563:1;:10;;;;;:::i;:::-;;8554:6;:19;8553:26;;8544:35;;8628:1;8617:6;8613:1;:10;;;;;:::i;:::-;;8604:6;:19;8603:26;;8594:35;;8678:1;8667:6;8663:1;:10;;;;;:::i;:::-;;8654:6;:19;8653:26;;8644:35;;8728:1;8717:6;8713:1;:10;;;;;:::i;:::-;;8704:6;:19;8703:26;;8694:35;;8778:1;8767:6;8763:1;:10;;;;;:::i;:::-;;8754:6;:19;8753:26;;8744:35;;8828:1;8817:6;8813:1;:10;;;;;:::i;:::-;;8804:6;:19;8803:26;;8794:35;;8851:23;8855:6;8867;8863:1;:10;;;;;:::i;:::-;;8851:3;:23::i;87222:448::-;87384:7;87404:237;87417:4;87411:3;:10;87404:237;;;87438:11;87452:23;87465:3;87470:4;87452:12;:23::i;:::-;88727:28;88792:20;;;88858:4;88845:18;;87438:37;;-1:-1:-1;87494:35:0;;;;88841:28;;87494:29;;;:35;87490:140;;;87557:3;87550:10;;87490:140;;;87607:7;:3;87613:1;87607:7;:::i;:::-;87601:13;;87490:140;87423:218;87404:237;;;-1:-1:-1;87658:4:0;87222:448;-1:-1:-1;;;87222:448:0:o;106976:232::-;107076:10;;-1:-1:-1;;;107076:10:0;;;;;;107057:16;107097:22;;;:11;;;;:22;;;;;;:30;;;;107163:26;;-1:-1:-1;;;;;107163:26:0;;;107176:13;;;;107163:26;;;;;106976:232::o;64630:411::-;64851:14;;;64862:2;64851:14;;;;;;;;;64689:13;;65238:4;65202:40;;;64715:11;;64851:14;;;64862:2;;64851:14;;;-1:-1:-1;;;64944:16:0;;;-1:-1:-1;64990:4:0;64981:14;;64974:28;;;;-1:-1:-1;64944:16:0;64630:411::o;207354:907::-;207555:33;207591:26;;;:14;:26;;;;;;;;207639:30;;;:21;;;:30;;;;;;;;;207638:31;207630:83;;;;-1:-1:-1;;;207630:83:0;;41500:2:1;207630:83:0;;;41482:21:1;41539:2;41519:18;;;41512:30;41578:34;41558:18;;;41551:62;-1:-1:-1;;;41629:18:1;;;41622:37;41676:19;;207630:83:0;41298:403:1;207630:83:0;207741:1;207732:6;:10;207724:63;;;;-1:-1:-1;;;207724:63:0;;41908:2:1;207724:63:0;;;41890:21:1;41947:2;41927:18;;;41920:30;41986:34;41966:18;;;41959:62;-1:-1:-1;;;42037:18:1;;;42030:38;42085:19;;207724:63:0;41706:404:1;207724:63:0;207798:30;;;;:21;;;:30;;;;;:37;;-1:-1:-1;;207798:37:0;207831:4;207798:37;;;207852:34;;;207848:406;;207932:6;207903:12;:25;;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;207848:406:0;;-1:-1:-1;207848:406:0;;-1:-1:-1;;207960:30:0;;;;207956:298;;208032:6;208007:12;:21;;;:31;;;;;;;:::i;207956:298::-;-1:-1:-1;;208060:34:0;;;;208056:198;;208140:6;208111:12;:25;;;:35;;;;;;;:::i;208056:198::-;208179:63;;-1:-1:-1;;;208179:63:0;;42317:2:1;208179:63:0;;;42299:21:1;42356:2;42336:18;;;42329:30;42395:34;42375:18;;;42368:62;-1:-1:-1;;;42446:18:1;;;42439:51;42507:19;;208179:63:0;42115:417:1;208056:198:0;207544:717;207354:907;;;;;:::o;104338:552::-;104499:17;;:21;104495:388;;104731:10;104725:17;104788:15;104775:10;104771:2;104767:19;104760:44;104495:388;104858:12;104851:20;;-1:-1:-1;;;104851:20:0;;;;;;;;:::i;141596:268::-;141649:7;141681:4;-1:-1:-1;;;;;141690:11:0;141673:28;;:63;;;;;141722:14;141705:13;:31;141673:63;141669:188;;;-1:-1:-1;141760:22:0;;141596:268::o;141669:188::-;141822:23;141964:81;;;139695:95;141964:81;;;44671:25:1;141987:11:0;44712:18:1;;;44705:34;;;;142000:14:0;44755:18:1;;;44748:34;142016:13:0;44798:18:1;;;44791:34;142039:4:0;44841:19:1;;;44834:61;141927:7:0;;44643:19:1;;141964:81:0;;;;;;;;;;;;141954:92;;;;;;141947:99;;141872:182;;133642:1477;133730:7;;134664:66;134651:79;;134647:163;;;-1:-1:-1;134763:1:0;;-1:-1:-1;134767:30:0;134747:51;;134647:163;134924:24;;;134907:14;134924:24;;;;;;;;;42764:25:1;;;42837:4;42825:17;;42805:18;;;42798:45;;;;42859:18;;;42852:34;;;42902:18;;;42895:34;;;134924:24:0;;42736:19:1;;134924:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;134924:24:0;;-1:-1:-1;;134924:24:0;;;-1:-1:-1;;;;;;;134963:20:0;;134959:103;;135016:1;135020:29;135000:50;;;;;;;134959:103;135082:6;-1:-1:-1;135090:20:0;;-1:-1:-1;133642:1477:0;;;;;;;;:::o;129102:521::-;129180:20;129171:5;:29;;;;;;;;:::i;:::-;;129167:449;;129102:521;:::o;129167:449::-;129278:29;129269:5;:38;;;;;;;;:::i;:::-;;129265:351;;129324:34;;-1:-1:-1;;;129324:34:0;;43142:2:1;129324:34:0;;;43124:21:1;43181:2;43161:18;;;43154:30;43220:26;43200:18;;;43193:54;43264:18;;129324:34:0;42940:348:1;129265:351:0;129389:35;129380:5;:44;;;;;;;;:::i;:::-;;129376:240;;129441:41;;-1:-1:-1;;;129441:41:0;;43495:2:1;129441:41:0;;;43477:21:1;43534:2;43514:18;;;43507:30;43573:33;43553:18;;;43546:61;43624:18;;129441:41:0;43293:355:1;129376:240:0;129513:30;129504:5;:39;;;;;;;;:::i;:::-;;129500:116;;129560:44;;-1:-1:-1;;;129560:44:0;;43855:2:1;129560:44:0;;;43837:21:1;43894:2;43874:18;;;43867:30;43933:34;43913:18;;;43906:62;-1:-1:-1;;;43984:18:1;;;43977:32;44026:19;;129560:44:0;43653:398:1;86026:857:0;86160:11;;86117:7;;;;86188;;86184:692;;86265:25;86293:28;86307:4;86313:7;86319:1;86313:3;:7;:::i;86293:28::-;86265:56;;;;;;;;;;;;;;;;;;-1:-1:-1;;;86265:56:0;;;-1:-1:-1;;;;;86265:56:0;;;;;;;-1:-1:-1;86402:16:0;;;-1:-1:-1;86402:16:0;86394:56;;;;-1:-1:-1;;;86394:56:0;;44258:2:1;86394:56:0;;;44240:21:1;44297:2;44277:18;;;44270:30;44336:29;44316:18;;;44309:57;44383:18;;86394:56:0;44056:351:1;86394:56:0;86517:9;;:16;;;;;;;86513:193;;86592:5;86554:28;86568:4;86574:7;86580:1;86574:3;:7;:::i;86554:28::-;:43;;-1:-1:-1;;;;;86554:43:0;;;;-1:-1:-1;;;86554:43:0;;;;;;;;;;;86513:193;;;86648:41;;;;;;;;;;;;;;;-1:-1:-1;;;;;86648:41:0;;;;;;;;;;86638:52;;;;;;;-1:-1:-1;86638:52:0;;;;;;;;;;;;;;-1:-1:-1;;;86638:52:0;;;;;;;;;;86513:193;86728:11;;;;-1:-1:-1;86741:5:0;;-1:-1:-1;86720:27:0;;-1:-1:-1;86720:27:0;86184:692;-1:-1:-1;;86790:41:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;86790:41:0;;;;;;;;;;86780:52;;;;;;;-1:-1:-1;86780:52:0;;;;;;;;;;;;;-1:-1:-1;;;86780:52:0;;;;;;;;;;;;-1:-1:-1;;86824:5:0;86847:17;;1266:106;1324:7;1355:1;1351;:5;:13;;1363:1;1351:13;;;-1:-1:-1;1359:1:0;;1344:20;-1:-1:-1;1266:106:0:o;9370:1019::-;9422:7;;9509:3;9500:12;;;:16;9496:102;;9547:3;9537:13;;;;9569;9496:102;9625:2;9616:11;;;:15;9612:99;;9662:2;9652:12;;;;9683;9612:99;9738:2;9729:11;;;:15;9725:99;;9775:2;9765:12;;;;9796;9725:99;9851:2;9842:11;;;:15;9838:99;;9888:2;9878:12;;;;9909;9838:99;9964:1;9955:10;;;:14;9951:96;;10000:1;9990:11;;;;10020;9951:96;10074:1;10065:10;;;:14;10061:96;;10110:1;10100:11;;;;10130;10061:96;10184:1;10175:10;;;:14;10171:96;;10220:1;10210:11;;;;10240;10171:96;10294:1;10285:10;;;:14;10281:66;;10330:1;10320:11;10375:6;9370:1019;-1:-1:-1;;9370:1019:0:o;1448:106::-;1506:7;1537:1;1533;:5;:13;;1545:1;1533:13;;1673:156;1735:7;1810:11;1820:1;1811:5;;;1810:11;:::i;:::-;1800:21;;1801:5;;;1800:21;:::i;14:286:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;679:180;738:6;791:2;779:9;770:7;766:23;762:32;759:52;;;807:1;804;797:12;759:52;-1:-1:-1;830:23:1;;679:180;-1:-1:-1;679:180:1:o;864:250::-;949:1;959:113;973:6;970:1;967:13;959:113;;;1049:11;;;1043:18;1030:11;;;1023:39;995:2;988:10;959:113;;;-1:-1:-1;;1106:1:1;1088:16;;1081:27;864:250::o;1119:271::-;1161:3;1199:5;1193:12;1226:6;1221:3;1214:19;1242:76;1311:6;1304:4;1299:3;1295:14;1288:4;1281:5;1277:16;1242:76;:::i;:::-;1372:2;1351:15;-1:-1:-1;;1347:29:1;1338:39;;;;1379:4;1334:50;;1119:271;-1:-1:-1;;1119:271:1:o;1395:220::-;1544:2;1533:9;1526:21;1507:4;1564:45;1605:2;1594:9;1590:18;1582:6;1564:45;:::i;1620:131::-;-1:-1:-1;;;;;1695:31:1;;1685:42;;1675:70;;1741:1;1738;1731:12;1756:247;1815:6;1868:2;1856:9;1847:7;1843:23;1839:32;1836:52;;;1884:1;1881;1874:12;1836:52;1923:9;1910:23;1942:31;1967:5;1942:31;:::i;2008:127::-;2069:10;2064:3;2060:20;2057:1;2050:31;2100:4;2097:1;2090:15;2124:4;2121:1;2114:15;2140:275;2211:2;2205:9;2276:2;2257:13;;-1:-1:-1;;2253:27:1;2241:40;;-1:-1:-1;;;;;2296:34:1;;2332:22;;;2293:62;2290:88;;;2358:18;;:::i;:::-;2394:2;2387:22;2140:275;;-1:-1:-1;2140:275:1:o;2420:183::-;2480:4;-1:-1:-1;;;;;2505:6:1;2502:30;2499:56;;;2535:18;;:::i;:::-;-1:-1:-1;2580:1:1;2576:14;2592:4;2572:25;;2420:183::o;2608:737::-;2662:5;2715:3;2708:4;2700:6;2696:17;2692:27;2682:55;;2733:1;2730;2723:12;2682:55;2769:6;2756:20;2795:4;2819:60;2835:43;2875:2;2835:43;:::i;:::-;2819:60;:::i;:::-;2913:15;;;2999:1;2995:10;;;;2983:23;;2979:32;;;2944:12;;;;3023:15;;;3020:35;;;3051:1;3048;3041:12;3020:35;3087:2;3079:6;3075:15;3099:217;3115:6;3110:3;3107:15;3099:217;;;3195:3;3182:17;3212:31;3237:5;3212:31;:::i;:::-;3256:18;;3294:12;;;;3132;;3099:217;;3350:662;3404:5;3457:3;3450:4;3442:6;3438:17;3434:27;3424:55;;3475:1;3472;3465:12;3424:55;3511:6;3498:20;3537:4;3561:60;3577:43;3617:2;3577:43;:::i;3561:60::-;3655:15;;;3741:1;3737:10;;;;3725:23;;3721:32;;;3686:12;;;;3765:15;;;3762:35;;;3793:1;3790;3783:12;3762:35;3829:2;3821:6;3817:15;3841:142;3857:6;3852:3;3849:15;3841:142;;;3923:17;;3911:30;;3961:12;;;;3874;;3841:142;;4017:186;4065:4;-1:-1:-1;;;;;4090:6:1;4087:30;4084:56;;;4120:18;;:::i;:::-;-1:-1:-1;4186:2:1;4165:15;-1:-1:-1;;4161:29:1;4192:4;4157:40;;4017:186::o;4208:336::-;4272:5;4301:52;4317:35;4345:6;4317:35;:::i;4301:52::-;4292:61;;4376:6;4369:5;4362:21;4416:3;4407:6;4402:3;4398:16;4395:25;4392:45;;;4433:1;4430;4423:12;4392:45;4482:6;4477:3;4470:4;4463:5;4459:16;4446:43;4536:1;4529:4;4520:6;4513:5;4509:18;4505:29;4498:40;4208:336;;;;;:::o;4549:220::-;4591:5;4644:3;4637:4;4629:6;4625:17;4621:27;4611:55;;4662:1;4659;4652:12;4611:55;4684:79;4759:3;4750:6;4737:20;4730:4;4722:6;4718:17;4684:79;:::i;4774:886::-;4826:5;4879:3;4872:4;4864:6;4860:17;4856:27;4846:55;;4897:1;4894;4887:12;4846:55;4933:6;4920:20;4959:4;4983:60;4999:43;5039:2;4999:43;:::i;4983:60::-;5077:15;;;5163:1;5159:10;;;;5147:23;;5143:32;;;5108:12;;;;5187:15;;;5184:35;;;5215:1;5212;5205:12;5184:35;5251:2;5243:6;5239:15;5263:368;5279:6;5274:3;5271:15;5263:368;;;5365:3;5352:17;-1:-1:-1;;;;;5388:11:1;5385:35;5382:125;;;5461:1;5490:2;5486;5479:14;5382:125;5532:56;5584:3;5579:2;5565:11;5557:6;5553:24;5549:33;5532:56;:::i;:::-;5520:69;;-1:-1:-1;5609:12:1;;;;5296;;5263:368;;5665:1226;5854:6;5862;5870;5878;5886;5939:3;5927:9;5918:7;5914:23;5910:33;5907:53;;;5956:1;5953;5946:12;5907:53;5992:9;5979:23;5969:33;;6053:2;6042:9;6038:18;6025:32;-1:-1:-1;;;;;6117:2:1;6109:6;6106:14;6103:34;;;6133:1;6130;6123:12;6103:34;6156:61;6209:7;6200:6;6189:9;6185:22;6156:61;:::i;:::-;6146:71;;6270:2;6259:9;6255:18;6242:32;6226:48;;6299:2;6289:8;6286:16;6283:36;;;6315:1;6312;6305:12;6283:36;6338:63;6393:7;6382:8;6371:9;6367:24;6338:63;:::i;:::-;6328:73;;6454:2;6443:9;6439:18;6426:32;6410:48;;6483:2;6473:8;6470:16;6467:36;;;6499:1;6496;6489:12;6467:36;6522:61;6575:7;6564:8;6553:9;6549:24;6522:61;:::i;:::-;6512:71;;6636:3;6625:9;6621:19;6608:33;6592:49;;6666:2;6656:8;6653:16;6650:36;;;6682:1;6679;6672:12;6650:36;-1:-1:-1;6705:24:1;;6760:4;6752:13;;6748:27;-1:-1:-1;6738:55:1;;6789:1;6786;6779:12;6738:55;6812:73;6877:7;6872:2;6859:16;6854:2;6850;6846:11;6812:73;:::i;:::-;6802:83;;;5665:1226;;;;;;;;:::o;6896:383::-;6973:6;6981;6989;7042:2;7030:9;7021:7;7017:23;7013:32;7010:52;;;7058:1;7055;7048:12;7010:52;7097:9;7084:23;7116:31;7141:5;7116:31;:::i;:::-;7166:5;7218:2;7203:18;;7190:32;;-1:-1:-1;7269:2:1;7254:18;;;7241:32;;6896:383;-1:-1:-1;;;6896:383:1:o;7284:665::-;7379:6;7387;7395;7403;7456:3;7444:9;7435:7;7431:23;7427:33;7424:53;;;7473:1;7470;7463:12;7424:53;7512:9;7499:23;7531:31;7556:5;7531:31;:::i;:::-;7581:5;-1:-1:-1;7638:2:1;7623:18;;7610:32;7651:33;7610:32;7651:33;:::i;:::-;7703:7;-1:-1:-1;7757:2:1;7742:18;;7729:32;;-1:-1:-1;7812:2:1;7797:18;;7784:32;-1:-1:-1;;;;;7828:30:1;;7825:50;;;7871:1;7868;7861:12;7825:50;7894:49;7935:7;7926:6;7915:9;7911:22;7894:49;:::i;:::-;7884:59;;;7284:665;;;;;;;:::o;8573:348::-;8625:8;8635:6;8689:3;8682:4;8674:6;8670:17;8666:27;8656:55;;8707:1;8704;8697:12;8656:55;-1:-1:-1;8730:20:1;;-1:-1:-1;;;;;8762:30:1;;8759:50;;;8805:1;8802;8795:12;8759:50;8842:4;8834:6;8830:17;8818:29;;8894:3;8887:4;8878:6;8870;8866:19;8862:30;8859:39;8856:59;;;8911:1;8908;8901:12;8856:59;8573:348;;;;;:::o;8926:547::-;9015:6;9023;9031;9039;9092:2;9080:9;9071:7;9067:23;9063:32;9060:52;;;9108:1;9105;9098:12;9060:52;9144:9;9131:23;9121:33;;9201:2;9190:9;9186:18;9173:32;9163:42;;9256:2;9245:9;9241:18;9228:32;-1:-1:-1;;;;;9275:6:1;9272:30;9269:50;;;9315:1;9312;9305:12;9269:50;9354:59;9405:7;9396:6;9385:9;9381:22;9354:59;:::i;:::-;8926:547;;;;-1:-1:-1;9432:8:1;-1:-1:-1;;;;8926:547:1:o;9478:127::-;9539:10;9534:3;9530:20;9527:1;9520:31;9570:4;9567:1;9560:15;9594:4;9591:1;9584:15;9610:346;9760:2;9745:18;;9793:1;9782:13;;9772:144;;9838:10;9833:3;9829:20;9826:1;9819:31;9873:4;9870:1;9863:15;9901:4;9898:1;9891:15;9772:144;9925:25;;;9610:346;:::o;9961:897::-;10131:6;10139;10147;10155;10208:3;10196:9;10187:7;10183:23;10179:33;10176:53;;;10225:1;10222;10215:12;10176:53;10265:9;10252:23;-1:-1:-1;;;;;10335:2:1;10327:6;10324:14;10321:34;;;10351:1;10348;10341:12;10321:34;10374:61;10427:7;10418:6;10407:9;10403:22;10374:61;:::i;:::-;10364:71;;10488:2;10477:9;10473:18;10460:32;10444:48;;10517:2;10507:8;10504:16;10501:36;;;10533:1;10530;10523:12;10501:36;10556:63;10611:7;10600:8;10589:9;10585:24;10556:63;:::i;:::-;10546:73;;10672:2;10661:9;10657:18;10644:32;10628:48;;10701:2;10691:8;10688:16;10685:36;;;10717:1;10714;10707:12;10685:36;;10740:61;10793:7;10782:8;10771:9;10767:24;10740:61;:::i;:::-;9961:897;;;;-1:-1:-1;10730:71:1;;10848:2;10833:18;10820:32;;-1:-1:-1;;;9961:897:1:o;11618:1033::-;11797:6;11805;11813;11821;11829;11882:3;11870:9;11861:7;11857:23;11853:33;11850:53;;;11899:1;11896;11889:12;11850:53;11939:9;11926:23;-1:-1:-1;;;;;12009:2:1;12001:6;11998:14;11995:34;;;12025:1;12022;12015:12;11995:34;12048:61;12101:7;12092:6;12081:9;12077:22;12048:61;:::i;:::-;12038:71;;12162:2;12151:9;12147:18;12134:32;12118:48;;12191:2;12181:8;12178:16;12175:36;;;12207:1;12204;12197:12;12175:36;12230:63;12285:7;12274:8;12263:9;12259:24;12230:63;:::i;:::-;12220:73;;12346:2;12335:9;12331:18;12318:32;12302:48;;12375:2;12365:8;12362:16;12359:36;;;12391:1;12388;12381:12;12359:36;;12414:61;12467:7;12456:8;12445:9;12441:24;12414:61;:::i;:::-;12404:71;;;12522:2;12511:9;12507:18;12494:32;12484:42;;12576:3;12565:9;12561:19;12548:33;12590:31;12615:5;12590:31;:::i;:::-;12640:5;12630:15;;;11618:1033;;;;;;;;:::o;12656:248::-;12724:6;12732;12785:2;12773:9;12764:7;12760:23;12756:32;12753:52;;;12801:1;12798;12791:12;12753:52;-1:-1:-1;;12824:23:1;;;12894:2;12879:18;;;12866:32;;-1:-1:-1;12656:248:1:o;12909:435::-;12962:3;13000:5;12994:12;13027:6;13022:3;13015:19;13053:4;13082:2;13077:3;13073:12;13066:19;;13119:2;13112:5;13108:14;13140:1;13150:169;13164:6;13161:1;13158:13;13150:169;;;13225:13;;13213:26;;13259:12;;;;13294:15;;;;13186:1;13179:9;13150:169;;;-1:-1:-1;13335:3:1;;12909:435;-1:-1:-1;;;;;12909:435:1:o;13349:920::-;13755:3;13750;13746:13;13738:6;13734:26;13723:9;13716:45;13797:3;13792:2;13781:9;13777:18;13770:31;13697:4;13824:46;13865:3;13854:9;13850:19;13842:6;13824:46;:::i;:::-;13918:9;13910:6;13906:22;13901:2;13890:9;13886:18;13879:50;13952:33;13978:6;13970;13952:33;:::i;:::-;14016:2;14001:18;;13994:34;;;-1:-1:-1;;;;;14065:32:1;;14059:3;14044:19;;14037:61;14085:3;14114:19;;14107:35;;;14179:22;;;14173:3;14158:19;;14151:51;13938:47;-1:-1:-1;14219:44:1;13938:47;14248:6;14219:44;:::i;:::-;14211:52;13349:920;-1:-1:-1;;;;;;;;;;13349:920:1:o;14475:1071::-;14629:6;14637;14645;14653;14661;14714:3;14702:9;14693:7;14689:23;14685:33;14682:53;;;14731:1;14728;14721:12;14682:53;14770:9;14757:23;14789:31;14814:5;14789:31;:::i;:::-;14839:5;-1:-1:-1;14896:2:1;14881:18;;14868:32;14909:33;14868:32;14909:33;:::i;:::-;14961:7;-1:-1:-1;15019:2:1;15004:18;;14991:32;-1:-1:-1;;;;;15072:14:1;;;15069:34;;;15099:1;15096;15089:12;15069:34;15122:61;15175:7;15166:6;15155:9;15151:22;15122:61;:::i;:::-;15112:71;;15236:2;15225:9;15221:18;15208:32;15192:48;;15265:2;15255:8;15252:16;15249:36;;;15281:1;15278;15271:12;15249:36;15304:63;15359:7;15348:8;15337:9;15333:24;15304:63;:::i;:::-;15294:73;;15420:3;15409:9;15405:19;15392:33;15376:49;;15450:2;15440:8;15437:16;15434:36;;;15466:1;15463;15456:12;15434:36;;15489:51;15532:7;15521:8;15510:9;15506:24;15489:51;:::i;15551:156::-;15617:20;;15677:4;15666:16;;15656:27;;15646:55;;15697:1;15694;15687:12;15712:838;15826:6;15834;15842;15850;15858;15866;15919:3;15907:9;15898:7;15894:23;15890:33;15887:53;;;15936:1;15933;15926:12;15887:53;15972:9;15959:23;15949:33;;16029:2;16018:9;16014:18;16001:32;15991:42;;16052:36;16084:2;16073:9;16069:18;16052:36;:::i;:::-;16042:46;;16139:2;16128:9;16124:18;16111:32;-1:-1:-1;;;;;16203:2:1;16195:6;16192:14;16189:34;;;16219:1;16216;16209:12;16189:34;16258:59;16309:7;16300:6;16289:9;16285:22;16258:59;:::i;:::-;16336:8;;-1:-1:-1;16232:85:1;-1:-1:-1;16424:3:1;16409:19;;16396:33;;-1:-1:-1;16441:16:1;;;16438:36;;;16470:1;16467;16460:12;16438:36;;16493:51;16536:7;16525:8;16514:9;16510:24;16493:51;:::i;:::-;16483:61;;;15712:838;;;;;;;;:::o;16555:613::-;16643:6;16651;16659;16667;16720:2;16708:9;16699:7;16695:23;16691:32;16688:52;;;16736:1;16733;16726:12;16688:52;16775:9;16762:23;16794:31;16819:5;16794:31;:::i;:::-;16844:5;-1:-1:-1;16896:2:1;16881:18;;16868:32;;-1:-1:-1;16951:2:1;16936:18;;16923:32;-1:-1:-1;;;;;16967:30:1;;16964:50;;;17010:1;17007;17000:12;17173:618;17269:6;17277;17285;17293;17301;17354:3;17342:9;17333:7;17329:23;17325:33;17322:53;;;17371:1;17368;17361:12;17322:53;17407:9;17394:23;17384:33;;17464:2;17453:9;17449:18;17436:32;17426:42;;17487:36;17519:2;17508:9;17504:18;17487:36;:::i;:::-;17477:46;;17574:2;17563:9;17559:18;17546:32;-1:-1:-1;;;;;17593:6:1;17590:30;17587:50;;;17633:1;17630;17623:12;17587:50;17672:59;17723:7;17714:6;17703:9;17699:22;17672:59;:::i;:::-;17173:618;;;;-1:-1:-1;17173:618:1;;-1:-1:-1;17750:8:1;;17646:85;17173:618;-1:-1:-1;;;17173:618:1:o;17796:592::-;17891:6;17899;17907;17915;17968:3;17956:9;17947:7;17943:23;17939:33;17936:53;;;17985:1;17982;17975:12;17936:53;18024:9;18011:23;18043:31;18068:5;18043:31;:::i;:::-;18093:5;-1:-1:-1;18145:2:1;18130:18;;18117:32;;-1:-1:-1;18196:2:1;18181:18;;18168:32;;-1:-1:-1;18251:2:1;18236:18;;18223:32;-1:-1:-1;;;;;18267:30:1;;18264:50;;;18310:1;18307;18300:12;18393:318;18468:6;18476;18484;18537:2;18525:9;18516:7;18512:23;18508:32;18505:52;;;18553:1;18550;18543:12;18505:52;18589:9;18576:23;18566:33;;18646:2;18635:9;18631:18;18618:32;18608:42;;18669:36;18701:2;18690:9;18686:18;18669:36;:::i;:::-;18659:46;;18393:318;;;;;:::o;18716:734::-;18820:6;18828;18836;18844;18852;18905:3;18893:9;18884:7;18880:23;18876:33;18873:53;;;18922:1;18919;18912:12;18873:53;18961:9;18948:23;18980:31;19005:5;18980:31;:::i;:::-;19030:5;-1:-1:-1;19087:2:1;19072:18;;19059:32;19100:33;19059:32;19100:33;:::i;:::-;19152:7;-1:-1:-1;19206:2:1;19191:18;;19178:32;;-1:-1:-1;19257:2:1;19242:18;;19229:32;;-1:-1:-1;19312:3:1;19297:19;;19284:33;-1:-1:-1;;;;;19329:30:1;;19326:50;;;19372:1;19369;19362:12;19326:50;19395:49;19436:7;19427:6;19416:9;19412:22;19395:49;:::i;19455:1047::-;19594:6;19602;19610;19618;19626;19634;19642;19650;19658;19711:3;19699:9;19690:7;19686:23;19682:33;19679:53;;;19728:1;19725;19718:12;19679:53;19764:9;19751:23;19741:33;;19821:2;19810:9;19806:18;19793:32;19783:42;;19844:36;19876:2;19865:9;19861:18;19844:36;:::i;:::-;19834:46;;19931:2;19920:9;19916:18;19903:32;-1:-1:-1;;;;;19995:2:1;19987:6;19984:14;19981:34;;;20011:1;20008;20001:12;19981:34;20050:59;20101:7;20092:6;20081:9;20077:22;20050:59;:::i;:::-;20128:8;;-1:-1:-1;20024:85:1;-1:-1:-1;20216:3:1;20201:19;;20188:33;;-1:-1:-1;20233:16:1;;;20230:36;;;20262:1;20259;20252:12;20230:36;;20285:51;20328:7;20317:8;20306:9;20302:24;20285:51;:::i;:::-;20275:61;;;20355:37;20387:3;20376:9;20372:19;20355:37;:::i;:::-;20345:47;;20439:3;20428:9;20424:19;20411:33;20401:43;;20491:3;20480:9;20476:19;20463:33;20453:43;;19455:1047;;;;;;;;;;;:::o;20507:527::-;20607:6;20615;20623;20631;20639;20647;20700:3;20688:9;20679:7;20675:23;20671:33;20668:53;;;20717:1;20714;20707:12;20668:53;20753:9;20740:23;20730:33;;20810:2;20799:9;20795:18;20782:32;20772:42;;20833:36;20865:2;20854:9;20850:18;20833:36;:::i;:::-;20823:46;;20888:36;20920:2;20909:9;20905:18;20888:36;:::i;:::-;20878:46;;20971:3;20960:9;20956:19;20943:33;20933:43;;21023:3;21012:9;21008:19;20995:33;20985:43;;20507:527;;;;;;;;:::o;21615:271::-;21798:6;21790;21785:3;21772:33;21754:3;21824:16;;21849:13;;;21824:16;21615:271;-1:-1:-1;21615:271:1:o;21891:380::-;21970:1;21966:12;;;;22013;;;22034:61;;22088:4;22080:6;22076:17;22066:27;;22034:61;22141:2;22133:6;22130:14;22110:18;22107:38;22104:161;;22187:10;22182:3;22178:20;22175:1;22168:31;22222:4;22219:1;22212:15;22250:4;22247:1;22240:15;22104:161;;21891:380;;;:::o;22276:127::-;22337:10;22332:3;22328:20;22325:1;22318:31;22368:4;22365:1;22358:15;22392:4;22389:1;22382:15;22408:128;22475:9;;;22496:11;;;22493:37;;;22510:18;;:::i;22959:397::-;23161:2;23143:21;;;23200:2;23180:18;;;23173:30;23239:34;23234:2;23219:18;;23212:62;-1:-1:-1;;;23305:2:1;23290:18;;23283:31;23346:3;23331:19;;22959:397::o;24116:125::-;24181:9;;;24202:10;;;24199:36;;;24215:18;;:::i;24246:461::-;24299:3;24337:5;24331:12;24364:6;24359:3;24352:19;24390:4;24419:2;24414:3;24410:12;24403:19;;24456:2;24449:5;24445:14;24477:1;24487:195;24501:6;24498:1;24495:13;24487:195;;;24566:13;;-1:-1:-1;;;;;24562:39:1;24550:52;;24622:12;;;;24657:15;;;;24598:1;24516:9;24487:195;;24712:615;24763:3;24801:5;24795:12;24828:6;24823:3;24816:19;24854:4;24895:2;24890:3;24886:12;24920:11;24947;24940:18;;24997:6;24994:1;24990:14;24983:5;24979:26;24967:38;;25039:2;25032:5;25028:14;25060:1;25070:231;25084:6;25081:1;25078:13;25070:231;;;25155:5;25149:4;25145:16;25140:3;25133:29;25183:38;25216:4;25207:6;25201:13;25183:38;:::i;:::-;25279:12;;;;25175:46;-1:-1:-1;25244:15:1;;;;25106:1;25099:9;25070:231;;;-1:-1:-1;25317:4:1;;24712:615;-1:-1:-1;;;;;;;24712:615:1:o;25332:1864::-;25906:4;25935:3;25965:6;25954:9;25947:25;25991:2;26058:1;26054;26049:3;26045:11;26041:19;26033:6;26029:32;26024:2;26013:9;26009:18;26002:60;26098:2;26093;26082:9;26078:18;26071:30;26124:56;26176:2;26165:9;26161:18;26153:6;26124:56;:::i;:::-;26110:70;;26228:9;26220:6;26216:22;26211:2;26200:9;26196:18;26189:50;26262:44;26299:6;26291;26262:44;:::i;:::-;26248:58;;26355:9;26347:6;26343:22;26337:3;26326:9;26322:19;26315:51;26386:6;26421;26415:13;26452:6;26444;26437:22;26487:2;26479:6;26475:15;26468:22;;26546:2;26536:6;26533:1;26529:14;26521:6;26517:27;26513:36;26584:2;26576:6;26572:15;26605:1;26615:252;26629:6;26626:1;26623:13;26615:252;;;26719:2;26715:7;26706:6;26698;26694:19;26690:33;26685:3;26678:46;26747:40;26780:6;26771;26765:13;26747:40;:::i;:::-;26845:12;;;;26737:50;-1:-1:-1;26810:15:1;;;;26651:1;26644:9;26615:252;;;26619:3;;26916:9;26908:6;26904:22;26898:3;26887:9;26883:19;26876:51;26950:42;26985:6;26977;26950:42;:::i;:::-;26936:56;;;;;;27029:6;27023:3;27012:9;27008:19;27001:35;27073:6;27067:3;27056:9;27052:19;27045:35;27129:9;27121:6;27117:22;27111:3;27100:9;27096:19;27089:51;27157:33;27183:6;27175;27157:33;:::i;:::-;27149:41;25332:1864;-1:-1:-1;;;;;;;;;;;;25332:1864:1:o;27561:184::-;27631:6;27684:2;27672:9;27663:7;27659:23;27655:32;27652:52;;;27700:1;27697;27690:12;27652:52;-1:-1:-1;27723:16:1;;27561:184;-1:-1:-1;27561:184:1:o;27750:168::-;27823:9;;;27854;;27871:15;;;27865:22;;27851:37;27841:71;;27892:18;;:::i;27923:127::-;27984:10;27979:3;27975:20;27972:1;27965:31;28015:4;28012:1;28005:15;28039:4;28036:1;28029:15;28055:120;28095:1;28121;28111:35;;28126:18;;:::i;:::-;-1:-1:-1;28160:9:1;;28055:120::o;28584:390::-;28743:2;28732:9;28725:21;28782:6;28777:2;28766:9;28762:18;28755:34;28839:6;28831;28826:2;28815:9;28811:18;28798:48;28895:1;28866:22;;;28890:2;28862:31;;;28855:42;;;;28958:2;28937:15;;;-1:-1:-1;;28933:29:1;28918:45;28914:54;;28584:390;-1:-1:-1;28584:390:1:o;30097:251::-;30167:6;30220:2;30208:9;30199:7;30195:23;30191:32;30188:52;;;30236:1;30233;30226:12;30188:52;30268:9;30262:16;30287:31;30312:5;30287:31;:::i;30353:648::-;30433:6;30486:2;30474:9;30465:7;30461:23;30457:32;30454:52;;;30502:1;30499;30492:12;30454:52;30535:9;30529:16;-1:-1:-1;;;;;30560:6:1;30557:30;30554:50;;;30600:1;30597;30590:12;30554:50;30623:22;;30676:4;30668:13;;30664:27;-1:-1:-1;30654:55:1;;30705:1;30702;30695:12;30654:55;30734:2;30728:9;30759:48;30775:31;30803:2;30775:31;:::i;30759:48::-;30830:2;30823:5;30816:17;30870:7;30865:2;30860;30856;30852:11;30848:20;30845:33;30842:53;;;30891:1;30888;30881:12;30842:53;30904:67;30968:2;30963;30956:5;30952:14;30947:2;30943;30939:11;30904:67;:::i;31006:127::-;31067:10;31062:3;31058:20;31055:1;31048:31;31098:4;31095:1;31088:15;31122:4;31119:1;31112:15;31540:284;31609:6;31662:2;31650:9;31641:7;31637:23;31633:32;31630:52;;;31678:1;31675;31668:12;31630:52;31710:9;31704:16;31760:14;31753:5;31749:26;31742:5;31739:37;31729:65;;31790:1;31787;31780:12;31829:856;32238:3;32227:9;32220:22;32201:4;32265:57;32317:3;32306:9;32302:19;32294:6;32265:57;:::i;:::-;32370:9;32362:6;32358:22;32353:2;32342:9;32338:18;32331:50;32404:44;32441:6;32433;32404:44;:::i;:::-;32390:58;;32496:9;32488:6;32484:22;32479:2;32468:9;32464:18;32457:50;32524:42;32559:6;32551;32524:42;:::i;:::-;32597:2;32582:18;;32575:34;;;;-1:-1:-1;;;;;;;32646:32:1;;;;32640:3;32625:19;;;32618:61;32516:50;31829:856;-1:-1:-1;;;31829:856:1:o;34632:275::-;34717:6;34770:2;34758:9;34749:7;34745:23;34741:32;34738:52;;;34786:1;34783;34776:12;34738:52;34818:9;34812:16;34857:1;34850:5;34847:12;34837:40;;34873:1;34870;34863:12;35936:691;36034:6;36087:3;36075:9;36066:7;36062:23;36058:33;36055:53;;;36104:1;36101;36094:12;36055:53;36137:2;36131:9;36179:3;36171:6;36167:16;36249:6;36237:10;36234:22;-1:-1:-1;;;;;36201:10:1;36198:34;36195:62;36192:88;;;36260:18;;:::i;:::-;36296:2;36289:22;36335:16;;36320:32;;36395:2;36380:18;;36374:25;36408:31;36374:25;36408:31;:::i;:::-;36467:2;36455:15;;36448:30;36532:2;36517:18;;;36511:25;36494:15;;;36487:50;36591:2;36576:18;;;36570:25;36553:15;;;36546:50;;;;-1:-1:-1;36459:6:1;35936:691;-1:-1:-1;35936:691:1:o;37397:135::-;37436:3;37457:17;;;37454:43;;37477:18;;:::i;:::-;-1:-1:-1;37524:1:1;37513:13;;37397:135::o;37537:287::-;37666:3;37704:6;37698:13;37720:66;37779:6;37774:3;37767:4;37759:6;37755:17;37720:66;:::i;:::-;37802:16;;;;;37537:287;-1:-1:-1;;37537:287:1:o;38640:442::-;38869:6;38858:9;38851:25;38924:4;38916:6;38912:17;38907:2;38896:9;38892:18;38885:45;38966:6;38961:2;38950:9;38946:18;38939:34;39009:3;39004:2;38993:9;38989:18;38982:31;38832:4;39030:46;39071:3;39060:9;39056:19;39048:6;39030:46;:::i;39087:604::-;39362:6;39351:9;39344:25;39417:4;39409:6;39405:17;39400:2;39389:9;39385:18;39378:45;39459:6;39454:2;39443:9;39439:18;39432:34;39502:3;39497:2;39486:9;39482:18;39475:31;39325:4;39529:46;39570:3;39559:9;39555:19;39547:6;39529:46;:::i;:::-;39624:9;39616:6;39612:22;39606:3;39595:9;39591:19;39584:51;39652:33;39678:6;39670;39652:33;:::i;40104:179::-;40172:14;40219:10;;;40207;;;40203:27;;40242:12;;;40239:38;;;40257:18;;:::i;:::-;40239:38;40104:179;;;;:::o;40569:195::-;40608:1;40634:14;40675:2;40672:1;40668:10;40697:3;40687:37;;40704:18;;:::i;:::-;40742:10;;40738:20;;;;;40569:195;-1:-1:-1;;40569:195:1:o;41048:245::-;41127:6;41135;41188:2;41176:9;41167:7;41163:23;41159:32;41156:52;;;41204:1;41201;41194:12;41156:52;-1:-1:-1;;41227:16:1;;41283:2;41268:18;;;41262:25;41227:16;;41262:25;;-1:-1:-1;41048:245:1:o

Swarm Source

ipfs://129f3447433c59a981e767b2f1452563adddce84ada246938e565b4cf0250b85

Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

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.