ETH Price: $3,409.85 (-6.98%)

Contract

0xD39DFbfBA9E7eccd813918FfbDa10B783EA3b3C6
 
Transaction Hash
Method
Block
From
To
Withdraw Mt Fee ...211644572024-11-11 12:31:2338 days ago1731328283IN
DODO: WBTC - FBTC LP
0 ETH0.0017358319.09545172
Adjust Mt Fee Ra...205949492024-08-24 0:41:47118 days ago1724460107IN
DODO: WBTC - FBTC LP
0 ETH0.000025220.87634714
Adjust Mt Fee Ra...205243172024-08-14 3:54:59128 days ago1723607699IN
DODO: WBTC - FBTC LP
0 ETH0.000064472.23868341
Adjust Mt Fee Ra...203611252024-07-22 9:18:11150 days ago1721639891IN
DODO: WBTC - FBTC LP
0 ETH0.000132314.59447035
Adjust Mt Fee Ra...203481662024-07-20 13:53:11152 days ago1721483591IN
DODO: WBTC - FBTC LP
0 ETH0.0004732810.31135592
Sell Shares203307032024-07-18 3:23:35155 days ago1721273015IN
DODO: WBTC - FBTC LP
0 ETH0.000897286.9792613
Sell Shares203230272024-07-17 1:41:35156 days ago1721180495IN
DODO: WBTC - FBTC LP
0 ETH0.000756586.78769888
Sell Shares203230252024-07-17 1:41:11156 days ago1721180471IN
DODO: WBTC - FBTC LP
0 ETH0.000761096.8281255
Sell Shares203168582024-07-16 5:03:47156 days ago1721106227IN
DODO: WBTC - FBTC LP
0 ETH0.000563094.37989554
Adjust Mt Fee Ra...203110882024-07-15 9:42:47157 days ago1721036567IN
DODO: WBTC - FBTC LP
0 ETH0.000139075.81228428
Adjust Mt Fee Ra...202892382024-07-12 8:30:35160 days ago1720773035IN
DODO: WBTC - FBTC LP
0 ETH0.000108493.76735698
Adjust Mt Fee Ra...202831142024-07-11 11:58:11161 days ago1720699091IN
DODO: WBTC - FBTC LP
0 ETH0.000351617.66263555
Sell Shares202693582024-07-09 13:53:59163 days ago1720533239IN
DODO: WBTC - FBTC LP
0 ETH0.000559315.01739409
Init202628522024-07-08 16:01:47164 days ago1720454507IN
DODO: WBTC - FBTC LP
0 ETH0.001867377.06634226

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GSP

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-07-08
*/

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


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


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

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

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

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

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

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)



/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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

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


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


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

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

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

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/lib/DecimalMath.sol




/**
 * @title DecimalMath
 * @author DODO Breeder
 *
 * @notice Functions for fixed point number with 18 decimals
 */

library DecimalMath {
    uint256 internal constant ONE = 10 ** 18;
    uint256 internal constant ONE2 = 10 ** 36;

    function mul(uint256 target, uint256 d) internal pure returns (uint256) {
        return target * d / (10 ** 18);
    }

    function mulFloor(uint256 target, uint256 d) internal pure returns (uint256) {
        return target * d / (10 ** 18);
    }

    function mulCeil(uint256 target, uint256 d) internal pure returns (uint256) {
        return _divCeil(target * d, 10 ** 18);
    }

    function div(uint256 target, uint256 d) internal pure returns (uint256) {
        return target * (10 ** 18) / d;
    }

    function divFloor(uint256 target, uint256 d) internal pure returns (uint256) {
        return target * (10 ** 18) / d;
    }

    function divCeil(uint256 target, uint256 d) internal pure returns (uint256) {
        return _divCeil(target * (10 ** 18), d);
    }

    function reciprocalFloor(uint256 target) internal pure returns (uint256) {
        return uint256(10 ** 36) / target;
    }

    function reciprocalCeil(uint256 target) internal pure returns (uint256) {
        return _divCeil(uint256(10 ** 36), target);
    }

    function sqrt(uint256 target) internal pure returns (uint256) {
        return Math.sqrt(target * ONE);
    }

    function powFloor(uint256 target, uint256 e) internal pure returns (uint256) {
        if (e == 0) {
            return 10 ** 18;
        } else if (e == 1) {
            return target;
        } else {
            uint256 p = powFloor(target, e / 2);
            p = p * p / (10 ** 18);
            if (e % 2 == 1) {
                p = p * target / (10 ** 18);
            }
            return p;
        }
    }

    function _divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 quotient = a / b;
        uint256 remainder = a - quotient * b;
        if (remainder > 0) {
            return quotient + 1;
        } else {
            return quotient;
        }
    }
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/lib/DODOMath.sol


/**
 * @title DODOMath
 * @author DODO Breeder
 *
 * @notice Functions for complex calculating. Including ONE Integration and TWO Quadratic solutions
 */
library DODOMath {
    using Math for uint256;
    /*
        Integrate dodo curve from V1 to V2
        require V0>=V1>=V2>0
        res = (1-k)i(V1-V2)+ikV0*V0(1/V2-1/V1)
        let V1-V2=delta
        res = i*delta*(1-k+k(V0^2/V1/V2))

        i is the price of V-res trading pair

        support k=1 & k=0 case

        [round down]
    */
    function _GeneralIntegrate(
        uint256 V0,
        uint256 V1,
        uint256 V2,
        uint256 i,
        uint256 k
    ) internal pure returns (uint256) {
        require(V0 > 0, "TARGET_IS_ZERO");
        uint256 fairAmount = i * (V1 - V2); // i*delta
        if (k == 0) {
            return fairAmount / DecimalMath.ONE;
        }
        uint256 V0V0V1V2 = DecimalMath.divFloor(V0 * V0 / V1, V2);
        uint256 penalty = DecimalMath.mulFloor(k, V0V0V1V2); // k(V0^2/V1/V2)
        return (DecimalMath.ONE - k + penalty) * fairAmount / DecimalMath.ONE2;
    }

    /*
        Follow the integration function above
        i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2)
        Assume Q2=Q0, Given Q1 and deltaB, solve Q0

        i is the price of delta-V trading pair
        give out target of V

        support k=1 & k=0 case

        [round down]
    */
    function _SolveQuadraticFunctionForTarget(
        uint256 V1,
        uint256 delta,
        uint256 i,
        uint256 k
    ) internal pure returns (uint256) {
        if (k == 0) {
            return V1 + DecimalMath.mulFloor(i, delta);
        }
        // V0 = V1*(1+(sqrt-1)/2k)
        // sqrt = √(1+4kidelta/V1)
        // premium = 1+(sqrt-1)/2k
        // uint256 sqrt = (4 * k).mul(i).mul(delta).div(V1).add(DecimalMath.ONE2).sqrt();

        if (V1 == 0) {
            return 0;
        }
        uint256 sqrt;
        uint256 ki = 4 * k * i;

        if (ki == 0) {
            sqrt = DecimalMath.ONE;
        } else if ((ki * delta) / ki == delta) {
            sqrt =((ki * delta) / V1  + DecimalMath.ONE2).sqrt();
        } else {
            sqrt = (ki / V1 * delta + DecimalMath.ONE2).sqrt();
        }
        uint256 premium =
            DecimalMath.divFloor(sqrt - DecimalMath.ONE, k * 2) + DecimalMath.ONE;
        // V0 is greater than or equal to V1 according to the solution
        return DecimalMath.mulFloor(V1, premium);
    }

    /*
        Follow the integration expression above, we have:
        i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2)
        Given Q1 and deltaB, solve Q2
        This is a quadratic function and the standard version is
        aQ2^2 + bQ2 + c = 0, where
        a=1-k
        -b=(1-k)Q1-kQ0^2/Q1+i*deltaB
        c=-kQ0^2 
        and Q2=(-b+sqrt(b^2+4(1-k)kQ0^2))/2(1-k)
        note: another root is negative, abondan

        if deltaBSig=true, then Q2>Q1, user sell Q and receive B
        if deltaBSig=false, then Q2<Q1, user sell B and receive Q
        return |Q1-Q2|

        as we only support sell amount as delta, the deltaB is always negative
        the input ideltaB is actually -ideltaB in the equation

        i is the price of delta-V trading pair

        support k=1 & k=0 case

        [round down]
    */
    function _SolveQuadraticFunctionForTrade(
        uint256 V0,
        uint256 V1,
        uint256 delta,
        uint256 i,
        uint256 k
    ) internal pure returns (uint256) {
        require(V0 > 0, "TARGET_IS_ZERO");
        if (delta == 0) {
            return 0;
        }

        if (k == 0) {
            // why v1
            return DecimalMath.mulFloor(i, delta) > V1 ? V1 : DecimalMath.mulFloor(i, delta);
        }

        if (k == DecimalMath.ONE) {
            // if k==1
            // Q2=Q1/(1+ideltaBQ1/Q0/Q0)
            // temp = ideltaBQ1/Q0/Q0
            // Q2 = Q1/(1+temp)
            // Q1-Q2 = Q1*(1-1/(1+temp)) = Q1*(temp/(1+temp))
            // uint256 temp = i.mul(delta).mul(V1).div(V0.mul(V0));
            uint256 temp;
            uint256 idelta = i * (delta);
            if (idelta == 0) {
                temp = 0;
            } else if ((idelta * V1) / idelta == V1) {
                temp = (idelta * V1) / (V0 * V0);
            } else {
                temp = delta * (V1) / (V0) * (i) / (V0);
            }
            return V1 * (temp) / (temp + (DecimalMath.ONE));
        }

        // calculate -b value and sig
        // b = kQ0^2/Q1-i*deltaB-(1-k)Q1
        // part1 = (1-k)Q1 >=0
        // part2 = kQ0^2/Q1-i*deltaB >=0
        // bAbs = abs(part1-part2)
        // if part1>part2 => b is negative => bSig is false
        // if part2>part1 => b is positive => bSig is true
        uint256 part2 = k * (V0) / (V1) * (V0) + (i * (delta)); // kQ0^2/Q1-i*deltaB
        uint256 bAbs = (DecimalMath.ONE - k) * (V1); // (1-k)Q1

        bool bSig;
        if (bAbs >= part2) {
            bAbs = bAbs - part2;
            bSig = false;
        } else {
            bAbs = part2 - bAbs;
            bSig = true;
        }
        bAbs = bAbs / (DecimalMath.ONE);

        // calculate sqrt
        uint256 squareRoot = DecimalMath.mulFloor((DecimalMath.ONE - k) * (4), DecimalMath.mulFloor(k, V0) * (V0)); // 4(1-k)kQ0^2
        squareRoot = Math.sqrt((bAbs * bAbs) + squareRoot); // sqrt(b*b+4(1-k)kQ0*Q0)

        // final res
        uint256 denominator = (DecimalMath.ONE - k) * 2; // 2(1-k)
        uint256 numerator;
        if (bSig) {
            numerator = squareRoot - bAbs;
            if (numerator == 0) {
                revert("DODOMath: should not be 0");
            }
        } else {
            numerator = bAbs + squareRoot;
        }

        uint256 V2 = DecimalMath.divCeil(numerator, denominator);
        if (V2 > V1) {
            return 0;
        } else {
            return V1 - V2;
        }
    }
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/lib/PMMPricing.sol



/**
 * @title Pricing
 * @author DODO Breeder
 *
 * @notice DODO Pricing model
 */

library PMMPricing {

    enum RState {ONE, ABOVE_ONE, BELOW_ONE}

    struct PMMState {
        uint256 i;
        uint256 K;
        uint256 B;
        uint256 Q;
        uint256 B0;
        uint256 Q0;
        RState R;
    }

    // ============ buy & sell ============
    /**
     * @notice Inner calculation based on pmm algorithm, sell base
     * @param state The current PMM state
     * @param payBaseAmount The amount of base token user want to sell
     * @return receiveQuoteAmount The amount of quote token user will receive
     * @return newR The new R status after swap
     */
    function sellBaseToken(PMMState memory state, uint256 payBaseAmount)
        internal
        pure
        returns (uint256 receiveQuoteAmount, RState newR)
    {
        if (state.R == RState.ONE) {
            // case 1: R=1
            // R falls below one
            receiveQuoteAmount = _ROneSellBaseToken(state, payBaseAmount);
            newR = RState.BELOW_ONE;
        } else if (state.R == RState.ABOVE_ONE) {
            uint256 backToOnePayBase = state.B0 - state.B;
            uint256 backToOneReceiveQuote = state.Q - state.Q0;
            // case 2: R>1
            // complex case, R status depends on trading amount
            if (payBaseAmount < backToOnePayBase) {
                // case 2.1: R status do not change
                receiveQuoteAmount = _RAboveSellBaseToken(state, payBaseAmount);
                newR = RState.ABOVE_ONE;
                if (receiveQuoteAmount > backToOneReceiveQuote) {
                    // [Important corner case!] may enter this branch when some precision problem happens. And consequently contribute to negative spare quote amount
                    // to make sure spare quote>=0, mannually set receiveQuote=backToOneReceiveQuote
                    receiveQuoteAmount = backToOneReceiveQuote;
                }
            } else if (payBaseAmount == backToOnePayBase) {
                // case 2.2: R status changes to ONE
                receiveQuoteAmount = backToOneReceiveQuote;
                newR = RState.ONE;
            } else {
                // case 2.3: R status changes to BELOW_ONE
                receiveQuoteAmount = backToOneReceiveQuote + (
                    _ROneSellBaseToken(state, (payBaseAmount - backToOnePayBase))
                );
                newR = RState.BELOW_ONE;
            }
        } else {
            // state.R == RState.BELOW_ONE
            // case 3: R<1
            receiveQuoteAmount = _RBelowSellBaseToken(state, payBaseAmount);
            newR = RState.BELOW_ONE;
        }
    }

    /**
     * @notice Inner calculation based on pmm algorithm, sell quote
     * @param state The current PMM state
     * @param payQuoteAmount The amount of quote token user want to sell
     * @return receiveBaseAmount The amount of base token user will receive
     * @return newR The new R status after swap
     */
    function sellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
        internal
        pure
        returns (uint256 receiveBaseAmount, RState newR)
    {
        if (state.R == RState.ONE) {
            receiveBaseAmount = _ROneSellQuoteToken(state, payQuoteAmount);
            newR = RState.ABOVE_ONE;
        } else if (state.R == RState.ABOVE_ONE) {
            receiveBaseAmount = _RAboveSellQuoteToken(state, payQuoteAmount);
            newR = RState.ABOVE_ONE;
        } else {
            uint256 backToOnePayQuote = state.Q0 - state.Q;
            uint256 backToOneReceiveBase = state.B - state.B0;
            if (payQuoteAmount < backToOnePayQuote) {
                receiveBaseAmount = _RBelowSellQuoteToken(state, payQuoteAmount); 
                newR = RState.BELOW_ONE;
                if (receiveBaseAmount > backToOneReceiveBase) {
                    receiveBaseAmount = backToOneReceiveBase;
                }
            } else if (payQuoteAmount == backToOnePayQuote) {
                receiveBaseAmount = backToOneReceiveBase;
                newR = RState.ONE;
            } else {
                receiveBaseAmount = backToOneReceiveBase + (
                    _ROneSellQuoteToken(state, payQuoteAmount - backToOnePayQuote) 
                );
                newR = RState.ABOVE_ONE;
            }
        }
    }

    // ============ R = 1 cases ============

    function _ROneSellBaseToken(PMMState memory state, uint256 payBaseAmount)
        internal
        pure
        returns (
            uint256 // receiveQuoteToken
        )
    {
        // in theory Q2 <= targetQuoteTokenAmount
        // however when amount is close to 0, precision problems may cause Q2 > targetQuoteTokenAmount
        return
            DODOMath._SolveQuadraticFunctionForTrade(
                state.Q0,
                state.Q0,
                payBaseAmount,
                state.i,
                state.K
            );
    }

    function _ROneSellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
        internal
        pure
        returns (
            uint256 // receiveBaseToken
        )
    {
        return
            DODOMath._SolveQuadraticFunctionForTrade(
                state.B0,
                state.B0,
                payQuoteAmount,
                DecimalMath.reciprocalFloor(state.i),
                state.K
            );
    }

    // ============ R < 1 cases ============

    function _RBelowSellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
        internal
        pure
        returns (
            uint256 // receiveBaseToken
        )
    {
        return
            DODOMath._GeneralIntegrate(
                state.Q0,
                state.Q + payQuoteAmount,
                state.Q,
                DecimalMath.reciprocalFloor(state.i),
                state.K
            );
    }

    function _RBelowSellBaseToken(PMMState memory state, uint256 payBaseAmount)
        internal
        pure
        returns (
            uint256 // receiveQuoteToken
        )
    {
        return
            DODOMath._SolveQuadraticFunctionForTrade(
                state.Q0,
                state.Q,
                payBaseAmount,
                state.i,
                state.K
            );
    }

    // ============ R > 1 cases ============

    function _RAboveSellBaseToken(PMMState memory state, uint256 payBaseAmount)
        internal
        pure
        returns (
            uint256 // receiveQuoteToken
        )
    {
        return
            DODOMath._GeneralIntegrate(
                state.B0,
                state.B + payBaseAmount,
                state.B,
                state.i,
                state.K
            );
    }

    function _RAboveSellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
        internal
        pure
        returns (
            uint256 // receiveBaseToken
        )
    {
        return
            DODOMath._SolveQuadraticFunctionForTrade(
                state.B0,
                state.B,
                payQuoteAmount,
                DecimalMath.reciprocalFloor(state.i),
                state.K
            );
    }

    // ============ Helper functions ============

    function adjustedTarget(PMMState memory state) internal pure {
        if (state.R == RState.BELOW_ONE) {
            state.Q0 = DODOMath._SolveQuadraticFunctionForTarget(
                state.Q,
                state.B - state.B0,
                state.i,
                state.K
            );
        } else if (state.R == RState.ABOVE_ONE) {
            state.B0 = DODOMath._SolveQuadraticFunctionForTarget(
                state.B,
                state.Q - state.Q0,
                DecimalMath.reciprocalFloor(state.i),
                state.K
            );
        }
    }

    function getMidPrice(PMMState memory state) internal pure returns (uint256) {
        if (state.R == RState.BELOW_ONE) {
            uint256 R = DecimalMath.divFloor(state.Q0 * state.Q0 / state.Q, state.Q);
            R = DecimalMath.ONE - state.K + (DecimalMath.mulFloor(state.K, R));
            return DecimalMath.divFloor(state.i, R);
        } else {
            uint256 R = DecimalMath.divFloor(state.B0 * state.B0 / state.B, state.B);
            R = DecimalMath.ONE - state.K + (DecimalMath.mulFloor(state.K, R));
            return DecimalMath.mulFloor(state.i, R);
        }
    }
}

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol


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



/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

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


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



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

// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol


// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)





/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

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

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

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

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

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


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



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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

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

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

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

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/GasSavingPool/impl/GSPStorage.sol


/// @notice this contract is used for store state and read state
contract GSPStorage is ReentrancyGuard {

    // ============ Storage for Setup ============
    // _GSP_INITIALIZED_ will be set to true when the init function is called
    bool internal _GSP_INITIALIZED_;
    // GSP does not open TWAP by default
    // _IS_OPEN_TWAP_ can be set to true when the init function is called
    bool public _IS_OPEN_TWAP_ = false;
    
    // ============ Core Address ============
    // _MAINTAINER_ is the maintainer of GSP
    address public _MAINTAINER_;
    // _ADMIN_ can set price
    address public _ADMIN_;
    // _BASE_TOKEN_ and _QUOTE_TOKEN_ should be ERC20 token
    IERC20 public _BASE_TOKEN_;
    IERC20 public _QUOTE_TOKEN_;
    // _BASE_RESERVE_ and _QUOTE_RESERVE_ are the current reserves of the GSP
    uint112 public _BASE_RESERVE_;
    uint112 public _QUOTE_RESERVE_;
    // _BLOCK_TIMESTAMP_LAST_ is used when calculating TWAP
    uint32 public _BLOCK_TIMESTAMP_LAST_;
    // _BASE_PRICE_CUMULATIVE_LAST_ is used when calculating TWAP
    uint256 public _BASE_PRICE_CUMULATIVE_LAST_;

    // _BASE_TARGET_ and _QUOTE_TARGET_ are recalculated when the pool state changes
    uint112 public _BASE_TARGET_;
    uint112 public _QUOTE_TARGET_;
    // _RState_ is the current R state of the GSP
    uint32 public _RState_;

    // ============ Shares (ERC20) ============
    // symbol is the symbol of the shares
    string public symbol;
    // decimals is the decimals of the shares
    uint8 public decimals;
    // name is the name of the shares
    string public name;
    // totalSupply is the total supply of the shares
    uint256 public totalSupply;
    // _SHARES_ is the mapping from account to share balance, record the share balance of each account
    mapping(address => uint256) internal _SHARES_;
    mapping(address => mapping(address => uint256)) internal _ALLOWED_;

    // ================= Permit ======================

    bytes32 public DOMAIN_SEPARATOR;
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    mapping(address => uint256) public nonces;

    // ============ Variables for Pricing ============
    // _MT_FEE_RATE_ is the fee rate of mt fee
    uint256 public _MT_FEE_RATE_;
    // _LP_FEE_RATE_ is the fee rate of lp fee
    uint256 public _LP_FEE_RATE_;
    uint256 public _K_;
    uint256 public _I_;
    // _PRICE_LIMIT_ is 1/1000 by default, which is used to limit the setting range of I
    uint256 public _PRICE_LIMIT_ = 1e3;

    // ============ Mt Fee ============
    // _MT_FEE_BASE_ represents the mt fee in base token
    uint256 public _MT_FEE_BASE_;
    // _MT_FEE_QUOTE_ represents the mt fee in quote token
    uint256 public _MT_FEE_QUOTE_;
    // _MT_FEE_RATE_MODEL_ is useless, just for compatible with old version pool
    address public _MT_FEE_RATE_MODEL_ = address(0);

    // ============ Helper Functions ============

    /// @notice Return the PMM state of the pool from inner or outside
    /// @dev B0 and Q0 are calculated in adjustedTarget
    /// @return state The current PMM state
    function getPMMState() public view returns (PMMPricing.PMMState memory state) {
        state.i = _I_;
        state.K = _K_;
        state.B = _BASE_RESERVE_;
        state.Q = _QUOTE_RESERVE_;
        state.B0 = _BASE_TARGET_; // will be calculated in adjustedTarget
        state.Q0 = _QUOTE_TARGET_;
        state.R = PMMPricing.RState(_RState_);
        PMMPricing.adjustedTarget(state);
    }

    /// @notice Return the PMM state variables used for routeHelpers
    /// @return i The price index
    /// @return K The K value
    /// @return B The base token reserve
    /// @return Q The quote token reserve
    /// @return B0 The base token target
    /// @return Q0 The quote token target
    /// @return R The R state of the pool
    function getPMMStateForCall()
        external
        view
        returns (
            uint256 i,
            uint256 K,
            uint256 B,
            uint256 Q,
            uint256 B0,
            uint256 Q0,
            uint256 R
        )
    {
        PMMPricing.PMMState memory state = getPMMState();
        i = state.i;
        K = state.K;
        B = state.B;
        Q = state.Q;
        B0 = state.B0;
        Q0 = state.Q0;
        R = uint256(state.R);
    }

    /// @notice Return the adjusted mid price
    /// @return midPrice The current mid price
    function getMidPrice() public view returns (uint256 midPrice) {
        return PMMPricing.getMidPrice(getPMMState());
    }

    /// @notice Return the total mt fee maintainer can claim
    /// @dev The total mt fee is represented in two types: in base token and in quote token
    /// @return mtFeeBase The total mt fee in base token
    /// @return mtFeeQuote The total mt fee in quote token
    function getMtFeeTotal() public view returns (uint256 mtFeeBase, uint256 mtFeeQuote) {
        mtFeeBase = _MT_FEE_BASE_;
        mtFeeQuote = _MT_FEE_QUOTE_;
    }
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/GasSavingPool/impl/GSPVault.sol


contract GSPVault is GSPStorage {
    using SafeERC20 for IERC20;

    // ============ Modifiers ============
    /// @notice Check whether the caller is maintainer
    modifier onlyMaintainer() {
        require(msg.sender == _MAINTAINER_, "ACCESS_DENIED");
        _;
    }

    /// @notice Check whether the caller is admin
    modifier onlyAdmin() {
        require(msg.sender == _ADMIN_, "ADMIN_ACCESS_DENIED");
        _;
    }

    // ============ Events ============

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    event Mint(address indexed user, uint256 value);

    event Burn(address indexed user, uint256 value);

    // ============ View Functions ============
    /**
     * @notice Get the reserves of the pool
     * @return baseReserve The base token reserve
     * @return quoteReserve The quote token reserve
     */
    function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve) {
        baseReserve = _BASE_RESERVE_;
        quoteReserve = _QUOTE_RESERVE_;
    }

    /**
     * @notice Get the fee rate of the pool
     * @param user Useless, just keep the same interface with old version pool
     * @return lpFeeRate The lp fee rate
     * @return mtFeeRate The mt fee rate
     */
    function getUserFeeRate(address user) 
        external 
        view 
        returns (uint256 lpFeeRate, uint256 mtFeeRate) 
    {
        lpFeeRate = _LP_FEE_RATE_;
        mtFeeRate = _MT_FEE_RATE_;
    }

    // ============ Asset In ============
    /**
     * @notice Get the amount of base token transferred in
     * @dev The amount of base token input should be the base token reserve minus the mt fee in base token
     * @return input The amount of base token transferred in
     */
    function getBaseInput() public view returns (uint256 input) {
        return _BASE_TOKEN_.balanceOf(address(this)) - uint256(_BASE_RESERVE_) - uint256(_MT_FEE_BASE_);
    }

    /**
     * @notice Get the amount of quote token transferred in
     * @dev The amount of quote token input should be the quote token reserve minus the mt fee in quote token
     * @return input The amount of quote token transferred in
     */
    function getQuoteInput() public view returns (uint256 input) {
        return _QUOTE_TOKEN_.balanceOf(address(this)) - uint256(_QUOTE_RESERVE_) - uint256(_MT_FEE_QUOTE_);
    }

    // ============ Set States ============
    /**
     * @notice Set the reserves of the pool, internal use only
     * @param baseReserve The base token reserve
     * @param quoteReserve The quote token reserve
     */
    function _setReserve(uint256 baseReserve, uint256 quoteReserve) internal {
        // the reserves should be less than the max uint112
        require(baseReserve <= type(uint112).max && quoteReserve <= type(uint112).max, "OVERFLOW");
        _BASE_RESERVE_ = uint112(baseReserve);
        _QUOTE_RESERVE_ = uint112(quoteReserve);
    }

    /**
     * @notice Sync the reserves of the pool, internal use only
     * @dev The balances of the pool should be actual balances minus the mt fee
     */
    function _sync() internal {
        uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)) - uint256(_MT_FEE_BASE_);
        uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)) - uint256(_MT_FEE_QUOTE_);
        // the reserves should be less than the max uint112
        require(baseBalance <= type(uint112).max && quoteBalance <= type(uint112).max, "OVERFLOW");
        if (baseBalance != _BASE_RESERVE_) {
            _BASE_RESERVE_ = uint112(baseBalance);
        }
        if (quoteBalance != _QUOTE_RESERVE_) {
            _QUOTE_RESERVE_ = uint112(quoteBalance);
        }
    }

    /// @notice Sync the reserves of the pool
    function sync() external nonReentrant {
        _sync();
    }

    /// @notice Correct the rState of the pool, details in pmm algorithm
    function correctRState() public {
        if (_RState_ == uint32(PMMPricing.RState.BELOW_ONE) && _BASE_RESERVE_<_BASE_TARGET_) {
          _RState_ = uint32(PMMPricing.RState.ONE);
          _BASE_TARGET_ = _BASE_RESERVE_;
          _QUOTE_TARGET_ = _QUOTE_RESERVE_;
        }
        if (_RState_ == uint32(PMMPricing.RState.ABOVE_ONE) && _QUOTE_RESERVE_<_QUOTE_TARGET_) {
          _RState_ = uint32(PMMPricing.RState.ONE);
          _BASE_TARGET_ = _BASE_RESERVE_;
          _QUOTE_TARGET_ = _QUOTE_RESERVE_;
        }
    }

    /**
     * @notice PriceLimit is used for oracle change protection
     * @notice It sets a ratio where the relative deviation between the new price and the old price cannot exceed this ratio.
     * @dev The default priceLimit is 1e3, the decimals of priceLimit is 1e6
     * @param priceLimit The new price limit
     */
    function adjustPriceLimit(uint256 priceLimit) external onlyAdmin {
        // the default priceLimit is 1e3
        require(priceLimit <= 1e6, "INVALID_PRICE_LIMIT");
        _PRICE_LIMIT_ = priceLimit;
    }

    /**
     * @notice Adjust oricle price i, only for admin
     */
    function adjustPrice(uint256 i) external onlyAdmin {
        // the difference between i and _I_ should be less than priceLimit
        uint256 offset = i > _I_ ? i - _I_ : _I_ - i;
        require((offset * 1e6 / _I_) <= _PRICE_LIMIT_, "EXCEED_PRICE_LIMIT");
        _I_ = i;
    }

    /**
     * @notice Adjust mtFee rate, only for maintainer
     * @dev The decimals of mtFee rate is 1e18
     * @param mtFeeRate The new mtFee rate
     */
    function adjustMtFeeRate(uint256 mtFeeRate) external onlyMaintainer {
        require(mtFeeRate <= 10**18, "INVALID_MT_FEE_RATE");
        _MT_FEE_RATE_ = mtFeeRate;
    }

    // ============ Asset Out ============
    /**
     * @notice Transfer base token out, internal use only
     * @param to The address of the receiver
     * @param amount The amount of base token to transfer out
     */
    function _transferBaseOut(address to, uint256 amount) internal {
        if (amount > 0) {
            _BASE_TOKEN_.safeTransfer(to, amount);
        }
    }

    /**
     * @notice Transfer quote token out, internal use only
     * @param to The address of the receiver
     * @param amount The amount of quote token to transfer out
     */
    function _transferQuoteOut(address to, uint256 amount) internal {
        if (amount > 0) {
            _QUOTE_TOKEN_.safeTransfer(to, amount);
        }
    }

    /// @notice Maintainer withdraw mtFee, only for maintainer
    function withdrawMtFeeTotal() external nonReentrant onlyMaintainer {
        uint256 mtFeeQuote = _MT_FEE_QUOTE_;
        uint256 mtFeeBase = _MT_FEE_BASE_;
        _MT_FEE_QUOTE_ = 0;
        _transferQuoteOut(_MAINTAINER_, mtFeeQuote);
        _MT_FEE_BASE_ = 0;
        _transferBaseOut(_MAINTAINER_, mtFeeBase);
    }

    // ============ Shares (ERC20) ============

    /**
     * @dev Transfer token for a specified address
     * @param to The address to transfer to.
     * @param amount The amount to be transferred.
     */
    function transfer(address to, uint256 amount) public returns (bool) {
        require(amount <= _SHARES_[msg.sender], "BALANCE_NOT_ENOUGH");

        _SHARES_[msg.sender] = _SHARES_[msg.sender] - (amount);
        _SHARES_[to] = _SHARES_[to] + amount;
        emit Transfer(msg.sender, to, amount);
        return true;
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner The address to query the the balance of.
     * @return balance An uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address owner) external view returns (uint256 balance) {
        return _SHARES_[owner];
    }

    /**
     * @dev Transfer tokens from one address to another
     * @param from address The address which you want to send tokens from
     * @param to address The address which you want to transfer to
     * @param amount uint256 the amount of tokens to be transferred
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public returns (bool) {
        require(amount <= _SHARES_[from], "BALANCE_NOT_ENOUGH");
        require(amount <= _ALLOWED_[from][msg.sender], "ALLOWANCE_NOT_ENOUGH");

        _SHARES_[from] = _SHARES_[from] - amount;
        _SHARES_[to] = _SHARES_[to] + amount;
        _ALLOWED_[from][msg.sender] = _ALLOWED_[from][msg.sender] - amount;
        emit Transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
     * @param spender The address which will spend the funds.
     * @param amount The amount of tokens to be spent.
     */
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) private {
        _ALLOWED_[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Function to check the amount of tokens that an owner _ALLOWED_ to a spender.
     * @param owner address The address which owns the funds.
     * @param spender address The address which will spend the funds.
     * @return A uint256 specifying the amount of tokens still available for the spender.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _ALLOWED_[owner][spender];
    }

    function _mint(address user, uint256 value) internal {
        require(value > 1000, "MINT_AMOUNT_NOT_ENOUGH");
        _SHARES_[user] = _SHARES_[user] + value;
        totalSupply = totalSupply + value;
        emit Mint(user, value);
        emit Transfer(address(0), user, value);
    }

    function _burn(address user, uint256 value) internal {
        _SHARES_[user] = _SHARES_[user] - value;
        totalSupply = totalSupply - value;
        emit Burn(user, value);
        emit Transfer(user, address(0), value);
    }

    // ============================ Permit ======================================

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(deadline >= block.timestamp, "DODO_GSP_LP: EXPIRED");
        bytes32 digest =
            keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    DOMAIN_SEPARATOR,
                    keccak256(
                        abi.encode(
                            PERMIT_TYPEHASH,
                            owner,
                            spender,
                            value,
                            nonces[owner]++,
                            deadline
                        )
                    )
                )
            );

        address recoveredAddress = ecrecover(digest, v, r, s);
        require(
            recoveredAddress != address(0) && recoveredAddress == owner,
            "DODO_GSP_LP: INVALID_SIGNATURE"
        );
        _approve(owner, spender, value);
    }
}
// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/intf/IDODOCallee.sol

interface IDODOCallee {
    function DVMSellShareCall(
        address sender,
        uint256 burnShareAmount,
        uint256 baseAmount,
        uint256 quoteAmount,
        bytes calldata data
    ) external;

    function DVMFlashLoanCall(
        address sender,
        uint256 baseAmount,
        uint256 quoteAmount,
        bytes calldata data
    ) external;

    function DPPFlashLoanCall(
        address sender,
        uint256 baseAmount,
        uint256 quoteAmount,
        bytes calldata data
    ) external;

    function DSPFlashLoanCall(
        address sender,
        uint256 baseAmount,
        uint256 quoteAmount,
        bytes calldata data
    ) external;

    function CPCancelCall(
        address sender,
        uint256 amount,
        bytes calldata data
    ) external;

	function CPClaimBidCall(
        address sender,
        uint256 baseAmount,
        uint256 quoteAmount,
        bytes calldata data
    ) external;

    function NFTRedeemCall(
        address payable assetTo,
        uint256 quoteAmount,
        bytes calldata
    ) external;
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/GasSavingPool/impl/GSPTrader.sol


/// @notice this contract deal with swap
contract GSPTrader is GSPVault {

    // ============ Events ============

    event DODOSwap(
        address fromToken,
        address toToken,
        uint256 fromAmount,
        uint256 toAmount,
        address trader,
        address receiver
    );

    event DODOFlashLoan(address borrower, address assetTo, uint256 baseAmount, uint256 quoteAmount);

    event RChange(PMMPricing.RState newRState);

    // ============ Trade Functions ============
    /**
     * @notice User sell base tokens, user pay tokens first. Must be used with a router
     * @dev The base token balance is the actual balance minus the mt fee
     * @param to The recipient of the output
     * @return receiveQuoteAmount Amount of quote token received
     */
    function sellBase(address to) external nonReentrant returns (uint256 receiveQuoteAmount) {
        uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)) - _MT_FEE_BASE_;
        uint256 baseInput = baseBalance - uint256(_BASE_RESERVE_);
        uint256 mtFee;
        uint256 newBaseTarget;
        PMMPricing.RState newRState;
        // calculate the amount of quote token to receive and mt fee
        (receiveQuoteAmount, mtFee, newRState, newBaseTarget) = querySellBase(tx.origin, baseInput);
        // transfer quote token to recipient
        _transferQuoteOut(to, receiveQuoteAmount);
        // update mt fee in quote token
        _MT_FEE_QUOTE_ = _MT_FEE_QUOTE_ + mtFee;
        

        // update TARGET
        if (_RState_ != uint32(newRState)) {    
            require(newBaseTarget <= type(uint112).max, "OVERFLOW");
            _BASE_TARGET_ = uint112(newBaseTarget);
            _RState_ = uint32(newRState);
            emit RChange(newRState);
        }
        // update reserve
        _setReserve(baseBalance, _QUOTE_TOKEN_.balanceOf(address(this)) - _MT_FEE_QUOTE_);

        emit DODOSwap(
            address(_BASE_TOKEN_),
            address(_QUOTE_TOKEN_),
            baseInput,
            receiveQuoteAmount,
            msg.sender,
            to
        );
    }

    /**
     * @notice User sell quote tokens, user pay tokens first. Must be used with a router
     * @param to The recipient of the output
     * @return receiveBaseAmount Amount of base token received
     */
    function sellQuote(address to) external nonReentrant returns (uint256 receiveBaseAmount) {
        uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)) - _MT_FEE_QUOTE_;
        uint256 quoteInput = quoteBalance - uint256(_QUOTE_RESERVE_);
        uint256 mtFee;
        uint256 newQuoteTarget;
        PMMPricing.RState newRState;
        // calculate the amount of base token to receive and mt fee
        (receiveBaseAmount, mtFee, newRState, newQuoteTarget) = querySellQuote(
            tx.origin,
            quoteInput
        );
        // transfer base token to recipient
        _transferBaseOut(to, receiveBaseAmount);
        // update mt fee in base token
        _MT_FEE_BASE_ = _MT_FEE_BASE_ + mtFee;

        // update TARGET
        if (_RState_ != uint32(newRState)) {
            require(newQuoteTarget <= type(uint112).max, "OVERFLOW");
            _QUOTE_TARGET_ = uint112(newQuoteTarget);
            _RState_ = uint32(newRState);
            emit RChange(newRState);
        }
        // update reserve
        _setReserve((_BASE_TOKEN_.balanceOf(address(this)) - _MT_FEE_BASE_), quoteBalance);

        emit DODOSwap(
            address(_QUOTE_TOKEN_),
            address(_BASE_TOKEN_),
            quoteInput,
            receiveBaseAmount,
            msg.sender,
            to
        );
    }

    /**
     * @notice inner flashloan, pay tokens out first, call external contract and check tokens left
     * @param baseAmount The base token amount user require
     * @param quoteAmount The quote token amount user require
     * @param assetTo The address who uses above tokens
     * @param data The external contract's callData
     */
    function flashLoan(
        uint256 baseAmount,
        uint256 quoteAmount,
        address assetTo,
        bytes calldata data
    ) external nonReentrant {
        _transferBaseOut(assetTo, baseAmount);
        _transferQuoteOut(assetTo, quoteAmount);

        if (data.length > 0)
            IDODOCallee(assetTo).DSPFlashLoanCall(msg.sender, baseAmount, quoteAmount, data);

        uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)) - _MT_FEE_BASE_;
        uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)) - _MT_FEE_QUOTE_;

        // no input -> pure loss
        require(
            baseBalance >= _BASE_RESERVE_ || quoteBalance >= _QUOTE_RESERVE_,
            "FLASH_LOAN_FAILED"
        );

        // sell quote case
        // quote input + base output
        if (baseBalance < _BASE_RESERVE_) {
            uint256 quoteInput = quoteBalance - uint256(_QUOTE_RESERVE_);
            (
                uint256 receiveBaseAmount,
                uint256 mtFee,
                PMMPricing.RState newRState,
                uint256 newQuoteTarget
            ) = querySellQuote(tx.origin, quoteInput); // revert if quoteBalance<quoteReserve
            require(
                (uint256(_BASE_RESERVE_) - baseBalance) <= receiveBaseAmount,
                "FLASH_LOAN_FAILED"
            );
            
            _MT_FEE_BASE_ = _MT_FEE_BASE_ + mtFee;
            
            if (_RState_ != uint32(newRState)) {
                require(newQuoteTarget <= type(uint112).max, "OVERFLOW");
                _QUOTE_TARGET_ = uint112(newQuoteTarget);
                _RState_ = uint32(newRState);
                emit RChange(newRState);
            }
            emit DODOSwap(
                address(_QUOTE_TOKEN_),
                address(_BASE_TOKEN_),
                quoteInput,
                receiveBaseAmount,
                msg.sender,
                assetTo
            );
        }

        // sell base case
        // base input + quote output
        if (quoteBalance < _QUOTE_RESERVE_) {
            uint256 baseInput = baseBalance - uint256(_BASE_RESERVE_);
            (
                uint256 receiveQuoteAmount,
                uint256 mtFee,
                PMMPricing.RState newRState,
                uint256 newBaseTarget
            ) = querySellBase(tx.origin, baseInput); // revert if baseBalance<baseReserve
            require(
                (uint256(_QUOTE_RESERVE_) - quoteBalance) <= receiveQuoteAmount,
                "FLASH_LOAN_FAILED"
            );

            _MT_FEE_QUOTE_ = _MT_FEE_QUOTE_ + mtFee;
            
            if (_RState_ != uint32(newRState)) {
                require(newBaseTarget <= type(uint112).max, "OVERFLOW");
                _BASE_TARGET_ = uint112(newBaseTarget);
                _RState_ = uint32(newRState);
                emit RChange(newRState);
            }
            emit DODOSwap(
                address(_BASE_TOKEN_),
                address(_QUOTE_TOKEN_),
                baseInput,
                receiveQuoteAmount,
                msg.sender,
                assetTo
            );
        }

        _sync();

        emit DODOFlashLoan(msg.sender, assetTo, baseAmount, quoteAmount);
    }

    // ============ Query Functions ============
    /**
     * @notice Return swap result, for query, sellBase side. 
     * @param trader Useless, just to keep the same interface with old version pool
     * @param payBaseAmount The amount of base token user want to sell
     * @return receiveQuoteAmount The amount of quote token user will receive
     * @return mtFee The amount of mt fee charged
     * @return newRState The new RState after swap
     * @return newBaseTarget The new base target after swap
     */
    function querySellBase(address trader, uint256 payBaseAmount)
        public
        view
        returns (
            uint256 receiveQuoteAmount,
            uint256 mtFee,
            PMMPricing.RState newRState,
            uint256 newBaseTarget
        )
    {
        PMMPricing.PMMState memory state = getPMMState();
        (receiveQuoteAmount, newRState) = PMMPricing.sellBaseToken(state, payBaseAmount);

        uint256 lpFeeRate = _LP_FEE_RATE_;
        uint256 mtFeeRate = _MT_FEE_RATE_;
        mtFee = DecimalMath.mulFloor(receiveQuoteAmount, mtFeeRate);
        receiveQuoteAmount = receiveQuoteAmount
            - DecimalMath.mulFloor(receiveQuoteAmount, lpFeeRate)
            - mtFee;
        newBaseTarget = state.B0;
    }
    /**
     * @notice Return swap result, for query, sellQuote side
     * @param trader Useless, just for keeping the same interface with old version pool
     * @param payQuoteAmount The amount of quote token user want to sell
     * @return receiveBaseAmount The amount of base token user will receive
     * @return mtFee The amount of mt fee charged
     * @return newRState The new RState after swap
     * @return newQuoteTarget The new quote target after swap
     */
    function querySellQuote(address trader, uint256 payQuoteAmount)
        public
        view
        returns (
            uint256 receiveBaseAmount,
            uint256 mtFee,
            PMMPricing.RState newRState,
            uint256 newQuoteTarget
        )
    {
        PMMPricing.PMMState memory state = getPMMState();
        (receiveBaseAmount, newRState) = PMMPricing.sellQuoteToken(state, payQuoteAmount);

        uint256 lpFeeRate = _LP_FEE_RATE_;
        uint256 mtFeeRate = _MT_FEE_RATE_;
        mtFee = DecimalMath.mulFloor(receiveBaseAmount, mtFeeRate);
        receiveBaseAmount = receiveBaseAmount
            - DecimalMath.mulFloor(receiveBaseAmount, lpFeeRate)
            - mtFee;
        newQuoteTarget = state.Q0;
    }
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/GasSavingPool/impl/GSPFunding.sol


/// @notice this part focus on Lp tokens, mint and burn
contract GSPFunding is GSPVault {
    // ============ Events ============

    event BuyShares(address to, uint256 increaseShares, uint256 totalShares);

    event SellShares(address payer, address to, uint256 decreaseShares, uint256 totalShares);

    // ============ Buy & Sell Shares ============
    
    /// @notice User mint Lp token and deposit tokens, the result is rounded down
    /// @dev User first transfer baseToken and quoteToken to GSP, then call buyShares
    /// @param to The address will receive shares
    /// @return shares The amount of shares user will receive
    /// @return baseInput The amount of baseToken user transfer to GSP
    /// @return quoteInput The amount of quoteToken user transfer to GSP
    function buyShares(address to)
        external
        nonReentrant
        returns (
            uint256 shares,
            uint256 baseInput,
            uint256 quoteInput
        )
    {
        // The balance of baseToken and quoteToken should be the balance minus the fee
        uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)) - _MT_FEE_BASE_;
        uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)) - _MT_FEE_QUOTE_;
        // The reserve of baseToken and quoteToken
        uint256 baseReserve = _BASE_RESERVE_;
        uint256 quoteReserve = _QUOTE_RESERVE_;

        // The amount of baseToken and quoteToken user transfer to GSP
        baseInput = baseBalance - baseReserve;
        quoteInput = quoteBalance - quoteReserve;

        // BaseToken should be transferred to GSP before calling buyShares
        require(baseInput > 0, "NO_BASE_INPUT");

        // Round down when withdrawing. Therefore, never be a situation occuring balance is 0 but totalsupply is not 0
        // But May Happen,reserve >0 But totalSupply = 0
        if (totalSupply == 0) {
            // case 1. initial supply
            require(quoteBalance > 0, "ZERO_QUOTE_AMOUNT");
            // The shares will be minted to user
            shares = quoteBalance < DecimalMath.mulFloor(baseBalance, _I_)
                ? DecimalMath.divFloor(quoteBalance, _I_)
                : baseBalance;
            // The target will be updated
            _BASE_TARGET_ = uint112(shares);
            _QUOTE_TARGET_ = uint112(DecimalMath.mulFloor(shares, _I_));
            require(_QUOTE_TARGET_ > 0, "QUOTE_TARGET_IS_ZERO");
            // Lock 1001 shares permanently in first deposit 
            require(shares > 2001, "MINT_AMOUNT_NOT_ENOUGH");
            _mint(address(0), 1001);
            shares -= 1001;
        } else if (baseReserve > 0 && quoteReserve > 0) {
            // case 2. normal case
            uint256 baseInputRatio = DecimalMath.divFloor(baseInput, baseReserve);
            uint256 quoteInputRatio = DecimalMath.divFloor(quoteInput, quoteReserve);
            uint256 mintRatio = quoteInputRatio < baseInputRatio ? quoteInputRatio : baseInputRatio;
            // The shares will be minted to user
            shares = DecimalMath.mulFloor(totalSupply, mintRatio);

            // The target will be updated
            _BASE_TARGET_ = uint112(uint256(_BASE_TARGET_) + (DecimalMath.mulFloor(uint256(_BASE_TARGET_), mintRatio)));
            _QUOTE_TARGET_ = uint112(uint256(_QUOTE_TARGET_) + (DecimalMath.mulFloor(uint256(_QUOTE_TARGET_), mintRatio)));
        }
        // The shares will be minted to user
        // The reserve will be updated
        _mint(to, shares);
        _setReserve(baseBalance, quoteBalance);
        emit BuyShares(to, shares, _SHARES_[to]);
    }

    /// @notice User burn their lp and withdraw their tokens, the result is rounded down
    /// @dev User call sellShares, the calculated baseToken and quoteToken amount should geater than minBaseToken and minQuoteToken
    /// @param shareAmount The amount of shares user want to sell
    /// @param to The address will receive baseToken and quoteToken
    /// @param baseMinAmount The minimum amount of baseToken user want to receive
    /// @param quoteMinAmount The minimum amount of quoteToken user want to receive
    /// @param data The data will be passed to callee contract
    /// @param deadline The deadline of this transaction
    function sellShares(
        uint256 shareAmount,
        address to,
        uint256 baseMinAmount,
        uint256 quoteMinAmount,
        bytes calldata data,
        uint256 deadline
    ) external nonReentrant returns (uint256 baseAmount, uint256 quoteAmount) {
        // The deadline should be greater than current timestamp
        require(deadline >= block.timestamp, "TIME_EXPIRED");
        // The amount of shares user want to sell should be less than user's balance
        require(shareAmount <= _SHARES_[msg.sender], "GLP_NOT_ENOUGH");

        // The balance of baseToken and quoteToken should be the balance minus the fee
        uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)) - _MT_FEE_BASE_;
        uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)) - _MT_FEE_QUOTE_;
        // The total shares of GSP
        uint256 totalShares = totalSupply;

        // The amount of baseToken and quoteToken user will receive is calculated by the ratio of user's shares to total shares
        baseAmount = baseBalance * shareAmount / totalShares;
        quoteAmount = quoteBalance * shareAmount / totalShares;
        
        // The target will be updated
        _BASE_TARGET_ = uint112(uint256(_BASE_TARGET_) - DecimalMath._divCeil((uint256(_BASE_TARGET_) * (shareAmount)), totalShares));
        _QUOTE_TARGET_ = uint112(uint256(_QUOTE_TARGET_) - DecimalMath._divCeil((uint256(_QUOTE_TARGET_) * (shareAmount)), totalShares));
        
        // The calculated baseToken and quoteToken amount should geater than minBaseToken and minQuoteToken
        require(
            baseAmount >= baseMinAmount && quoteAmount >= quoteMinAmount,
            "WITHDRAW_NOT_ENOUGH"
        );

        // The shares will be burned from user
        // The baseToken and quoteToken will be transferred to user
        // The reserve will be synced
        _burn(msg.sender, shareAmount);
        _transferBaseOut(to, baseAmount);
        _transferQuoteOut(to, quoteAmount);
        _sync();

        // If the data is not empty, the callee contract will be called
        if (data.length > 0) {
            //Same as DVM 
            IDODOCallee(to).DVMSellShareCall(
                msg.sender,
                shareAmount,
                baseAmount,
                quoteAmount,
                data
            );
        }

        emit SellShares(msg.sender, to, shareAmount, _SHARES_[msg.sender]);
    }
}

// File: dodo-gassaving-pool-main/dodo-gassaving-pool-main/contracts/GasSavingPool/impl/GSP.sol

/*

    Copyright 2020 DODO ZOO.
    SPDX-License-Identifier: Apache-2.0

*/

pragma solidity 0.8.16;

/**
 * @title DODO GasSavingPool
 * @author DODO Breeder
 *
 * @notice DODO GasSavingPool initialization
 */
contract GSP is GSPTrader, GSPFunding {
    /**
     * @notice Function will be called in factory, init risk should not be included.
     * @param maintainer The dodo's address, who can claim mtFee and own this pool
     * @param admin oracle owner address, who can set price.
     * @param baseTokenAddress The base token address
     * @param quoteTokenAddress The quote token address
     * @param lpFeeRate The rate of lp fee, with 18 decimal
     * @param mtFeeRate The rate of mt fee, with 18 decimal
     * @param i The oracle price, possible to be changed only by maintainer
     * @param k The swap curve parameter
     * @param isOpenTWAP Useless, always false, just for compatible with old version pool
     */
    function init(
        address maintainer,
        address admin,
        address baseTokenAddress,
        address quoteTokenAddress,
        uint256 lpFeeRate,
        uint256 mtFeeRate,
        uint256 i,
        uint256 k,
        bool isOpenTWAP
    ) external {
        // GSP can only be initialized once
        require(!_GSP_INITIALIZED_, "GSP_INITIALIZED");
        // _GSP_INITIALIZED_ is set to true after initialization
        _GSP_INITIALIZED_ = true;
        // baseTokenAddress and quoteTokenAddress should not be the same
        require(baseTokenAddress != quoteTokenAddress, "BASE_QUOTE_CAN_NOT_BE_SAME");
        // _BASE_TOKEN_ and _QUOTE_TOKEN_ should be valid ERC20 tokens
        _BASE_TOKEN_ = IERC20(baseTokenAddress);
        _QUOTE_TOKEN_ = IERC20(quoteTokenAddress);

        // i should be greater than 0 and less than 10**36
        require(i > 0 && i <= 10**36);
        _I_ = i;
        // k should be greater than 0 and less than 10**18
        require(k <= 10**18);
        _K_ = k;

        // _LP_FEE_RATE_ is set when initialization
        _LP_FEE_RATE_ = lpFeeRate;
        // _MT_FEE_RATE_ is set when initialization
        _MT_FEE_RATE_ = mtFeeRate;
        // _MAINTAINER_ is set when initialization, the address receives the fee
        _MAINTAINER_ = maintainer;
        _ADMIN_ = admin;
        // _IS_OPEN_TWAP_ is always false
        _IS_OPEN_TWAP_ = false;


        string memory connect = "_";
        string memory suffix = "GSP";
        // name of the shares is the combination of suffix, connect and string of the GSP
        name = string(abi.encodePacked(suffix, connect, addressToShortString(address(this))));
        // symbol of the shares is GLP
        symbol = "GLP";
        // decimals of the shares is the same as the base token decimals
        decimals = IERC20Metadata(baseTokenAddress).decimals();
        // initialize DOMAIN_SEPARATOR
        buildDomainSeparator();
        // ==========================================================================
    }

    // ============================== Permit ====================================
    /**
     * @notice DOMAIN_SEPARATOR is used for approve by signature
     */
    function buildDomainSeparator() public returns (bytes32){
        string memory connect = "_";
        string memory suffix = "GSP";
        // name of the shares is the combination of suffix, connect and string of the GSP
        string memory name = string(abi.encodePacked(suffix, connect, addressToShortString(address(this))));

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                // keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f,
                keccak256(bytes(name)),
                keccak256(bytes("1")),
                block.chainid,
                address(this)
            )
        );
        return DOMAIN_SEPARATOR;
    }

    /**
     * @notice Convert the address to a shorter string
     * @param _addr The address to convert
     * @return A string representation of _addr in hexadecimal
     */
    function addressToShortString(address _addr) public pure returns (string memory) {
        bytes32 value = bytes32(uint256(uint160(_addr)));
        bytes memory alphabet = "0123456789abcdef";

        bytes memory str = new bytes(8);
        for (uint256 i = 0; i < 4; i++) {
            str[i * 2] = alphabet[uint8(value[i + 12] >> 4)];
            str[1 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)];
        }
        return string(str);
    }

    // ============ Version Control ============
    /**
     * @notice Return the version of DODOGasSavingPool
     * @return The current version is 1.0.1
     */
    function version() external pure returns (string memory) {
        return "GSP 1.0.1";
    }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"increaseShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalShares","type":"uint256"}],"name":"BuyShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"assetTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"baseAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"name":"DODOFlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"fromToken","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"}],"name":"DODOSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum PMMPricing.RState","name":"newRState","type":"uint8"}],"name":"RChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"decreaseShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalShares","type":"uint256"}],"name":"SellShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_ADMIN_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_PRICE_CUMULATIVE_LAST_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_RESERVE_","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_TARGET_","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_TOKEN_","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BLOCK_TIMESTAMP_LAST_","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_IS_OPEN_TWAP_","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_I_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_K_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_LP_FEE_RATE_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MAINTAINER_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MT_FEE_BASE_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MT_FEE_QUOTE_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MT_FEE_RATE_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MT_FEE_RATE_MODEL_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_PRICE_LIMIT_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_QUOTE_RESERVE_","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_QUOTE_TARGET_","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_QUOTE_TOKEN_","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_RState_","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"addressToShortString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"mtFeeRate","type":"uint256"}],"name":"adjustMtFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"adjustPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"priceLimit","type":"uint256"}],"name":"adjustPriceLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buildDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"buyShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"baseInput","type":"uint256"},{"internalType":"uint256","name":"quoteInput","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"correctRState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBaseInput","outputs":[{"internalType":"uint256","name":"input","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMidPrice","outputs":[{"internalType":"uint256","name":"midPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMtFeeTotal","outputs":[{"internalType":"uint256","name":"mtFeeBase","type":"uint256"},{"internalType":"uint256","name":"mtFeeQuote","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPMMState","outputs":[{"components":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"K","type":"uint256"},{"internalType":"uint256","name":"B","type":"uint256"},{"internalType":"uint256","name":"Q","type":"uint256"},{"internalType":"uint256","name":"B0","type":"uint256"},{"internalType":"uint256","name":"Q0","type":"uint256"},{"internalType":"enum PMMPricing.RState","name":"R","type":"uint8"}],"internalType":"struct PMMPricing.PMMState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPMMStateForCall","outputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"K","type":"uint256"},{"internalType":"uint256","name":"B","type":"uint256"},{"internalType":"uint256","name":"Q","type":"uint256"},{"internalType":"uint256","name":"B0","type":"uint256"},{"internalType":"uint256","name":"Q0","type":"uint256"},{"internalType":"uint256","name":"R","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuoteInput","outputs":[{"internalType":"uint256","name":"input","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserFeeRate","outputs":[{"internalType":"uint256","name":"lpFeeRate","type":"uint256"},{"internalType":"uint256","name":"mtFeeRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultReserve","outputs":[{"internalType":"uint256","name":"baseReserve","type":"uint256"},{"internalType":"uint256","name":"quoteReserve","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maintainer","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"baseTokenAddress","type":"address"},{"internalType":"address","name":"quoteTokenAddress","type":"address"},{"internalType":"uint256","name":"lpFeeRate","type":"uint256"},{"internalType":"uint256","name":"mtFeeRate","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"k","type":"uint256"},{"internalType":"bool","name":"isOpenTWAP","type":"bool"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"payBaseAmount","type":"uint256"}],"name":"querySellBase","outputs":[{"internalType":"uint256","name":"receiveQuoteAmount","type":"uint256"},{"internalType":"uint256","name":"mtFee","type":"uint256"},{"internalType":"enum PMMPricing.RState","name":"newRState","type":"uint8"},{"internalType":"uint256","name":"newBaseTarget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"payQuoteAmount","type":"uint256"}],"name":"querySellQuote","outputs":[{"internalType":"uint256","name":"receiveBaseAmount","type":"uint256"},{"internalType":"uint256","name":"mtFee","type":"uint256"},{"internalType":"enum PMMPricing.RState","name":"newRState","type":"uint8"},{"internalType":"uint256","name":"newQuoteTarget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"sellBase","outputs":[{"internalType":"uint256","name":"receiveQuoteAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"sellQuote","outputs":[{"internalType":"uint256","name":"receiveBaseAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareAmount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"baseMinAmount","type":"uint256"},{"internalType":"uint256","name":"quoteMinAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellShares","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdrawMtFeeTotal","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526001805461ff00191690556103e8601455601780546001600160a01b031916905534801561003157600080fd5b5060016000556148b4806100466000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c8063880a4d87116101de578063d505accf1161010f578063ee27c689116100ad578063fcf709f71161007c578063fcf709f714610841578063fd1ed7e91461084c578063fe24cb7f14610889578063fff6cae91461089257600080fd5b8063ee27c68914610815578063f5346aea1461081d578063f6b06e7014610825578063f811d6921461083857600080fd5b8063e539ef49116100e9578063e539ef49146107de578063e6485c8e146107f1578063eb99da6a14610804578063ec2fd46d1461080c57600080fd5b8063d505accf1461077f578063dd62ed3e14610792578063dd93f59a146107cb57600080fd5b8063bbf5ce781161017c578063bfdbd72311610156578063bfdbd72314610747578063c0ffa17814610750578063d0a494e414610759578063d4b970461461076c57600080fd5b8063bbf5ce7814610703578063bd6015b41461071d578063bf357dae1461073057600080fd5b8063a9059cbb116101b8578063a9059cbb146106c1578063ab44a7a3146106d4578063b56ceaa6146106dd578063b59b8555146106f057600080fd5b8063880a4d871461067857806395d89b41146106a4578063a382d1b9146106ac57600080fd5b806347bbad2e116102c357806370a082311161026157806377f586571161023057806377f586571461060057806379a04876146106325780637d721504146106455780637ecebe001461065857600080fd5b806370a08231146105b457806371f9100c146105dd57806372bf079e146105e557806373d74cf8146105f857600080fd5b806354fd4d501161029d57806354fd4d501461055157806363ab59931461057657806365f6fcbb1461058957806366410a211461059157600080fd5b806347bbad2e146105075780634a248d2a146105105780634c85b4251461052357600080fd5b806330adf81f116103305780633644e5151161030a5780633644e515146104ab5780633afdfeba146104b45780634322ec83146104bd57806344096609146104ee57600080fd5b806330adf81f14610438578063313ce5671461045f57806336223ce91461047e57600080fd5b8063171019401161036c57806317101940146103e957806318160ddd146103fc57806323b872dd146104135780632df6cb481461042657600080fd5b806304b621bc1461039357806306fdde03146103a8578063095ea7b3146103c6575b600080fd5b6103a66103a1366004614013565b61089a565b005b6103b0610b2e565b6040516103bd91906140c7565b60405180910390f35b6103d96103d43660046140fa565b610bbc565b60405190151581526020016103bd565b6103b06103f7366004614124565b610bd3565b610405600b5481565b6040519081526020016103bd565b6103d961042136600461413f565b610d56565b6001546103d990610100900460ff1681565b6104057f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60095461046c9060ff1681565b60405160ff90911681526020016103bd565b6005546001600160701b0380821691600160701b9004165b604080519283526020830191909152016103bd565b610405600e5481565b61040560145481565b6001546104d6906201000090046001600160a01b031681565b6040516001600160a01b0390911681526020016103bd565b6104966104fc366004614124565b506011546010549091565b61040560165481565b6003546104d6906001600160a01b031681565b610536610531366004614124565b610f06565b604080519384526020840192909252908201526060016103bd565b60408051808201909152600981526847535020312e302e3160b81b60208201526103b0565b6002546104d6906001600160a01b031681565b610405611370565b6105a461059f3660046140fa565b611408565b6040516103bd94939291906141b3565b6104056105c2366004614124565b6001600160a01b03166000908152600c602052604090205490565b610405611471565b6103a66105f33660046141dd565b6114bf565b6103a66115a4565b60075461061a90600160701b90046001600160701b031681565b6040516001600160701b0390911681526020016103bd565b6105a46106403660046140fa565b61165b565b60055461061a906001600160701b031681565b610405610666366004614124565b600f6020526000908152604090205481565b60055461068f90600160e01b900463ffffffff1681565b60405163ffffffff90911681526020016103bd565b6103b06116c4565b6106b46116d1565b6040516103bd91906141f6565b6103d96106cf3660046140fa565b611773565b61040560115481565b6104966106eb36600461428f565b61185f565b6103a66106fe3660046141dd565b611c39565b60055461061a90600160701b90046001600160701b031681565b61040561072b366004614124565b611cdc565b60075461068f90600160e01b900463ffffffff1681565b61040560155481565b61040560105481565b6103a6610767366004614309565b611f55565b6004546104d6906001600160a01b031681565b6103a661078d366004614380565b612515565b6104056107a03660046143ed565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205490565b6104056107d9366004614124565b61272b565b60075461061a906001600160701b031681565b6103a66107ff3660046141dd565b612998565b6103a6612a36565b61040560125481565b610405612ae6565b610405612af8565b6017546104d6906001600160a01b031681565b61040560135481565b601554601654610496565b610854612c00565b604080519788526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0016103bd565b61040560065481565b6103a6612c62565b60015460ff16156108e45760405162461bcd60e51b815260206004820152600f60248201526e11d4d417d253925512505312569151608a1b60448201526064015b60405180910390fd5b6001805460ff1916811790556001600160a01b038087169088160361094b5760405162461bcd60e51b815260206004820152601a60248201527f424153455f51554f54455f43414e5f4e4f545f42455f53414d4500000000000060448201526064016108db565b600380546001600160a01b03808a166001600160a01b0319928316179092556004805492891692909116919091179055821580159061099957506ec097ce7bc90715b34b9f10000000008311155b6109a257600080fd5b6013839055670de0b6b3a76400008211156109bc57600080fd5b60128290556011859055601084905560018054600280546001600160a01b038c81166001600160a01b03199092169190911790915561ff0019908c16620100000216610100600160b01b0319909116178155604080518082018252918252605f60f81b6020808401919091528151808301909252600382526204753560ec1b908201528082610a4a30610bd3565b604051602001610a5c93929190614420565b604051602081830303815290604052600a9081610a799190614501565b506040805180820190915260038152620474c560ec1b6020820152600890610aa19082614501565b50886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0491906145c1565b6009805460ff191660ff92909216919091179055610b20612af8565b505050505050505050505050565b600a8054610b3b90614479565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6790614479565b8015610bb45780601f10610b8957610100808354040283529160200191610bb4565b820191906000526020600020905b815481529060010190602001808311610b9757829003601f168201915b505050505081565b6000610bc9338484612c7c565b5060015b92915050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b6020820152815160088082528184019093526060926001600160a01b038516929160009160208201818036833701905050905060005b6004811015610d4d5782600485610c4284600c6145f4565b60208110610c5257610c52614607565b1a60f81b6001600160f81b031916901c60f81c60ff1681518110610c7857610c78614607565b01602001516001600160f81b03191682610c9383600261461d565b81518110610ca357610ca3614607565b60200101906001600160f81b031916908160001a9053508284610cc783600c6145f4565b60208110610cd757610cd7614607565b825191901a600f16908110610cee57610cee614607565b01602001516001600160f81b03191682610d0983600261461d565b610d149060016145f4565b81518110610d2457610d24614607565b60200101906001600160f81b031916908160001a90535080610d458161463c565b915050610c2a565b50949350505050565b6001600160a01b0383166000908152600c6020526040812054821115610db35760405162461bcd60e51b81526020600482015260126024820152710848298829c868abe9c9ea8be8a9c9eaa8e960731b60448201526064016108db565b6001600160a01b0384166000908152600d60209081526040808320338452909152902054821115610e1d5760405162461bcd60e51b815260206004820152601460248201527308298989eae829c868abe9c9ea8be8a9c9eaa8e960631b60448201526064016108db565b6001600160a01b0384166000908152600c6020526040902054610e41908390614655565b6001600160a01b038086166000908152600c60205260408082209390935590851681522054610e719083906145f4565b6001600160a01b038085166000908152600c60209081526040808320949094559187168152600d82528281203382529091522054610eb0908390614655565b6001600160a01b038581166000818152600d60209081526040808320338452825291829020949094555185815291861692909160008051602061481f833981519152910160405180910390a35060019392505050565b6000806000610f13612cdd565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015610f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f849190614668565b610f8e9190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110049190614668565b61100e9190614655565b6005549091506001600160701b0380821691600160701b9004166110328285614655565b955061103e8184614655565b9450600086116110805760405162461bcd60e51b815260206004820152600d60248201526c1393d7d09054d157d253941555609a1b60448201526064016108db565b600b546000036111f957600083116110ce5760405162461bcd60e51b815260206004820152601160248201527016915493d7d45553d51157d05353d55395607a1b60448201526064016108db565b6110da84601354612d36565b83106110e657836110f2565b6110f283601354612d5c565b600780546001600160701b0319166001600160701b03831617905560135490975061111e908890612d36565b60078054600160701b600160e01b031916600160701b6001600160701b039384168102919091179182905590041661118f5760405162461bcd60e51b815260206004820152601460248201527351554f54455f5441524745545f49535f5a45524f60601b60448201526064016108db565b6107d187116111d95760405162461bcd60e51b815260206004820152601660248201527509a929ca8be829a9eaa9ca8be9c9ea8be8a9c9eaa8e960531b60448201526064016108db565b6111e660006103e9612d71565b6111f26103e988614655565b96506112f0565b6000821180156112095750600081115b156112f057600061121a8784612d5c565b905060006112288784612d5c565b90506000828210611239578261123b565b815b9050611249600b5482612d36565b600754909a50611262906001600160701b031682612d36565b60075461127891906001600160701b03166145f4565b600780546001600160701b0319166001600160701b0392831617908190556112a991600160701b9091041682612d36565b6007546112c69190600160701b90046001600160701b03166145f4565b6007600e6101000a8154816001600160701b0302191690836001600160701b031602179055505050505b6112fa8888612d71565b6113048484612e7b565b6001600160a01b0388166000818152600c60209081526040918290205482519384529083018a905282820152517f1c172440bdebb59cd92a7f08f4227903a3305ab6f880cb25f93eddb66843a1029181900360600190a1505050506113696001600055565b9193909250565b6015546005546003546040516370a0823160e01b8152306004820152600093926001600160701b0316916001600160a01b0316906370a08231906024015b602060405180830381865afa1580156113cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ef9190614668565b6113f99190614655565b6114039190614655565b905090565b60008060008060006114186116d1565b90506114248187612ee6565b6011546010549297509094509061143b8782612d36565b9550856114488884612d36565b6114529089614655565b61145c9190614655565b96508260a00151935050505092959194509250565b601654600554600480546040516370a0823160e01b8152309281019290925260009392600160701b90046001600160701b0316916001600160a01b03909116906370a08231906024016113ae565b6002546001600160a01b0316331461150f5760405162461bcd60e51b8152602060048201526013602482015272105113525397d050d0d154d4d7d11153925151606a1b60448201526064016108db565b6000601354821161152d57816013546115289190614655565b61153a565b60135461153a9083614655565b905060145460135482620f4240611551919061461d565b61155b9190614697565b111561159e5760405162461bcd60e51b8152602060048201526012602482015271115610d1515117d4149250d157d31253525560721b60448201526064016108db565b50601355565b60075463ffffffff600160e01b9091041660021480156115d457506007546005546001600160701b039182169116105b156115f957600554600160701b8082046001600160701b039081169091029116176007555b60075463ffffffff600160e01b90910416600114801561163457506007546005546001600160701b03600160701b9283900481169290910416105b1561165957600554600160701b8082046001600160701b039081169091029116176007555b565b600080600080600061166b6116d1565b90506116778187612fdb565b6011546010549297509094509061168e8782612d36565b95508561169b8884612d36565b6116a59089614655565b6116af9190614655565b96508260800151935050505092959194509250565b60088054610b3b90614479565b6116d9613fa1565b601354815260125460208201526005546001600160701b038082166040840152600160701b918290048116606084015260075480821660808501529182041660a0830152600160e01b900463ffffffff16600281111561173b5761173b61417b565b8160c0019060028111156117515761175161417b565b908160028111156117645761176461417b565b905250611770816130d8565b90565b336000908152600c60205260408120548211156117c75760405162461bcd60e51b81526020600482015260126024820152710848298829c868abe9c9ea8be8a9c9eaa8e960731b60448201526064016108db565b336000908152600c60205260409020546117e2908390614655565b336000908152600c6020526040808220929092556001600160a01b0385168152205461180f9083906145f4565b6001600160a01b0384166000818152600c602052604090819020929092559051339060008051602061481f8339815191529061184e9086815260200190565b60405180910390a350600192915050565b60008061186a612cdd565b428310156118a95760405162461bcd60e51b815260206004820152600c60248201526b1512535157d156141254915160a21b60448201526064016108db565b336000908152600c60205260409020548911156118f95760405162461bcd60e51b815260206004820152600e60248201526d08e98a0be9c9ea8be8a9c9eaa8e960931b60448201526064016108db565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015611946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196a9190614668565b6119749190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa1580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614668565b6119f49190614655565b600b5490915080611a058d8561461d565b611a0f9190614697565b945080611a1c8d8461461d565b611a269190614697565b600754909450611a4a90611a44908e906001600160701b031661461d565b8261317c565b600754611a6091906001600160701b0316614655565b600780546001600160701b0319166001600160701b039283161790819055611a9691611a44918f91600160701b9091041661461d565b600754611ab39190600160701b90046001600160701b0316614655565b6007600e6101000a8154816001600160701b0302191690836001600160701b03160217905550898510158015611ae95750888410155b611b2b5760405162461bcd60e51b81526020600482015260136024820152720ae92a89088a482aebe9c9ea8be8a9c9eaa8e9606b1b60448201526064016108db565b611b35338d6131c5565b611b3f8b8661327d565b611b498b8561329e565b611b516132bb565b8615611bc0578a6001600160a01b0316632411d338338e88888d8d6040518763ffffffff1660e01b8152600401611b8d969594939291906146e2565b600060405180830381600087803b158015611ba757600080fd5b505af1158015611bbb573d6000803e3d6000fd5b505050505b336000818152600c60209081526040918290205482519384526001600160a01b038f16918401919091528282018f90526060830152517f55caccde83781f39bfc1296eff45655b6496729443a7d48958b18b3b685600a59181900360800190a1505050611c2d6001600055565b97509795505050505050565b6001546201000090046001600160a01b03163314611c895760405162461bcd60e51b815260206004820152600d60248201526c1050d0d154d4d7d11153925151609a1b60448201526064016108db565b670de0b6b3a7640000811115611cd75760405162461bcd60e51b8152602060048201526013602482015272494e56414c49445f4d545f4645455f5241544560681b60448201526064016108db565b601055565b6000611ce6612cdd565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015611d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d579190614668565b611d619190614655565b600554909150600090611d7d906001600160701b031683614655565b90506000806000611d8e328561165b565b9298509094509092509050611da3878761329e565b82601654611db191906145f4565b601655806002811115611dc657611dc661417b565b600754600160e01b900463ffffffff908116911614611e79576001600160701b03821115611e065760405162461bcd60e51b81526004016108db90614722565b600780546001600160701b0319166001600160701b038416179055806002811115611e3357611e3361417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f83398151915281604051611e709190614744565b60405180910390a15b601654600480546040516370a0823160e01b81523092810192909252611f0092889290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef19190614668565b611efb9190614655565b612e7b565b60035460045460405160008051602061485f83398151915292611f39926001600160a01b039182169291169088908b9033908e90614752565b60405180910390a15050505050611f506001600055565b919050565b611f5d612cdd565b611f67838661327d565b611f71838561329e565b8015611fde5760405163d5b9979760e01b81526001600160a01b0384169063d5b9979790611fab903390899089908890889060040161478c565b600060405180830381600087803b158015611fc557600080fd5b505af1158015611fd9573d6000803e3d6000fd5b505050505b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa15801561202b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204f9190614668565b6120599190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa1580156120ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cf9190614668565b6120d99190614655565b6005549091506001600160701b0316821015806121085750600554600160701b90046001600160701b03168110155b6121245760405162461bcd60e51b81526004016108db906147ba565b6005546001600160701b03168210156122e85760055460009061215790600160701b90046001600160701b031683614655565b90506000806000806121693286611408565b60055493975091955093509150849061218c9089906001600160701b0316614655565b11156121aa5760405162461bcd60e51b81526004016108db906147ba565b826015546121b891906145f4565b6015558160028111156121cd576121cd61417b565b600754600160e01b900463ffffffff908116911614612289576001600160701b0381111561220d5760405162461bcd60e51b81526004016108db90614722565b60078054600160701b600160e01b031916600160701b6001600160701b038416021790558160028111156122435761224361417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f833981519152826040516122809190614744565b60405180910390a15b60008051602061485f833981519152600460009054906101000a90046001600160a01b0316600360009054906101000a90046001600160a01b03168787338f6040516122da96959493929190614752565b60405180910390a150505050505b600554600160701b90046001600160701b03168110156124aa5760055460009061231b906001600160701b031684614655565b905060008060008061232d328661165b565b600554939750919550935091508490612357908890600160701b90046001600160701b0316614655565b11156123755760405162461bcd60e51b81526004016108db906147ba565b8260165461238391906145f4565b6016558160028111156123985761239861417b565b600754600160e01b900463ffffffff90811691161461244b576001600160701b038111156123d85760405162461bcd60e51b81526004016108db90614722565b600780546001600160701b0319166001600160701b0383161790558160028111156124055761240561417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f833981519152826040516124429190614744565b60405180910390a15b60008051602061485f833981519152600360009054906101000a90046001600160a01b0316600460009054906101000a90046001600160a01b03168787338f60405161249c96959493929190614752565b60405180910390a150505050505b6124b26132bb565b604080513381526001600160a01b0387166020820152908101889052606081018790527f0b82e93068db15abd9fbb2682c65462ea8a0a10582dce93a5664818e296f54eb9060800160405180910390a1505061250e6001600055565b5050505050565b4284101561255c5760405162461bcd60e51b81526020600482015260146024820152731113d113d7d1d4d417d3140e881156141254915160621b60448201526064016108db565b600e546001600160a01b0388166000908152600f6020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9190876125af8361463c565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161262892919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612693573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906126c95750886001600160a01b0316816001600160a01b0316145b6127155760405162461bcd60e51b815260206004820152601e60248201527f444f444f5f4753505f4c503a20494e56414c49445f5349474e4154555245000060448201526064016108db565b612720898989612c7c565b505050505050505050565b6000612735612cdd565b601654600480546040516370a0823160e01b81523092810192909252600092916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ab9190614668565b6127b59190614655565b6005549091506000906127d890600160701b90046001600160701b031683614655565b905060008060006127e93285611408565b92985090945090925090506127fe878761327d565b8260155461280c91906145f4565b6015558060028111156128215761282161417b565b600754600160e01b900463ffffffff9081169116146128dd576001600160701b038211156128615760405162461bcd60e51b81526004016108db90614722565b60078054600160701b600160e01b031916600160701b6001600160701b038516021790558060028111156128975761289761417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f833981519152816040516128d49190614744565b60405180910390a15b6015546003546040516370a0823160e01b815230600482015261295f92916001600160a01b0316906370a0823190602401602060405180830381865afa15801561292b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294f9190614668565b6129599190614655565b86612e7b565b60045460035460405160008051602061485f83398151915292611f39926001600160a01b039182169291169088908b9033908e90614752565b6002546001600160a01b031633146129e85760405162461bcd60e51b8152602060048201526013602482015272105113525397d050d0d154d4d7d11153925151606a1b60448201526064016108db565b620f4240811115612a315760405162461bcd60e51b81526020600482015260136024820152721253959053125117d4149250d157d312535255606a1b60448201526064016108db565b601455565b612a3e612cdd565b6001546201000090046001600160a01b03163314612a8e5760405162461bcd60e51b815260206004820152600d60248201526c1050d0d154d4d7d11153925151609a1b60448201526064016108db565b601680546015546000909255600154909190612ab9906201000090046001600160a01b03168361329e565b6000601555600154612ada906201000090046001600160a01b03168261327d565b50506116596001600055565b6000611403612af36116d1565b613463565b60408051808201825260018152605f60f81b6020808301919091528251808401909352600383526204753560ec1b90830152600091828183612b3930610bd3565b604051602001612b4b93929190614420565b60408051601f198184030181528282528051602091820120838301835260018452603160f81b9382019390935281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81830152808301939093527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608401524660808401523060a0808501919091528251808503909101815260c09093019091528151910120600e819055949350505050565b600080600080600080600080612c146116d1565b905080600001519750806020015196508060400151955080606001519450806080015193508060a0015192508060c001516002811115612c5657612c5661417b565b91505090919293949596565b612c6a612cdd565b612c726132bb565b6116596001600055565b6001600160a01b038381166000818152600d602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600260005403612d2f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108db565b6002600055565b6000670de0b6b3a7640000612d4b838561461d565b612d559190614697565b9392505050565b600081612d4b84670de0b6b3a764000061461d565b6103e88111612dbb5760405162461bcd60e51b815260206004820152601660248201527509a929ca8be829a9eaa9ca8be9c9ea8be8a9c9eaa8e960531b60448201526064016108db565b6001600160a01b0382166000908152600c6020526040902054612ddf9082906145f4565b6001600160a01b0383166000908152600c6020526040902055600b54612e069082906145f4565b600b556040518181526001600160a01b038316907f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968859060200160405180910390a26040518181526001600160a01b0383169060009060008051602061481f833981519152906020015b60405180910390a35050565b6001600160701b038211801590612e9957506001600160701b038111155b612eb55760405162461bcd60e51b81526004016108db90614722565b600580546001600160701b03928316600160701b026001600160e01b03199091169290931691909117919091179055565b600080808460c001516002811115612f0057612f0061417b565b03612f1a57612f0f8484613562565b915060019050612fd4565b60018460c001516002811115612f3257612f3261417b565b03612f4157612f0f8484613589565b600084606001518560a00151612f579190614655565b9050600085608001518660400151612f6f9190614655565b905081851015612f9a57612f8386866135a6565b93506002925080841115612f95578093505b612fd1565b818503612fad5780935060009250612fd1565b612fc086612fbb8488614655565b613562565b612fca90826145f4565b9350600192505b50505b9250929050565b600080808460c001516002811115612ff557612ff561417b565b0361300f5761300484846135da565b915060029050612fd4565b60018460c0015160028111156130275761302761417b565b036130c3576000846040015185608001516130429190614655565b905060008560a00151866060015161305a9190614655565b9050818510156130855761306e86866135f9565b93506001925080841115613080578093505b6130bc565b81850361309857809350600092506130bc565b6130ab866130a68488614655565b6135da565b6130b590826145f4565b9350600292505b5050612fd4565b6130cd8484613624565b946002945092505050565b60028160c0015160028111156130f0576130f061417b565b036131255761311d8160600151826080015183604001516131119190614655565b83516020850151613643565b60a082015250565b60018160c00151600281111561313d5761313d61417b565b036131795761317381604001518260a00151836060015161315e9190614655565b83516131699061377b565b8460200151613643565b60808201525b50565b6000806131898385614697565b90506000613197848361461d565b6131a19086614655565b905080156131bd576131b48260016145f4565b92505050610bcd565b509050610bcd565b6001600160a01b0382166000908152600c60205260409020546131e9908290614655565b6001600160a01b0383166000908152600c6020526040902055600b54613210908290614655565b600b556040518181526001600160a01b038316907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59060200160405180910390a26040518181526000906001600160a01b0384169060008051602061481f83398151915290602001612e6f565b801561329a5760035461329a906001600160a01b03168383613796565b5050565b801561329a5760045461329a906001600160a01b03168383613796565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015613308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332c9190614668565b6133369190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa158015613388573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ac9190614668565b6133b69190614655565b90506001600160701b0382118015906133d657506001600160701b038111155b6133f25760405162461bcd60e51b81526004016108db90614722565b6005546001600160701b0316821461342057600580546001600160701b0319166001600160701b0384161790555b600554600160701b90046001600160701b0316811461329a57600580546001600160701b038316600160701b02600160701b600160e01b03199091161790555050565b600060028260c00151600281111561347d5761347d61417b565b036134f257606082015160a08301516000916134b19161349d908061461d565b6134a79190614697565b8460600151612d5c565b90506134c1836020015182612d36565b60208401516134d890670de0b6b3a7640000614655565b6134e291906145f4565b9050612d55836000015182612d5c565b604082015160808301516000916135219161350d908061461d565b6135179190614697565b8460400151612d5c565b9050613531836020015182612d36565b602084015161354890670de0b6b3a7640000614655565b61355291906145f4565b9050612d55836000015182612d36565b6000612d55836080015184608001518461357f876000015161377b565b87602001516137ed565b6000612d55836080015184604001518461357f876000015161377b565b6000612d558360a001518385606001516135c091906145f4565b606086015186516135d09061377b565b8760200151613aff565b6000612d558360a001518460a0015184866000015187602001516137ed565b6000612d55836080015183856040015161361391906145f4565b604086015186516020880151613aff565b6000612d558360a00151846060015184866000015187602001516137ed565b600081600003613668576136578385612d36565b61366190866145f4565b9050613773565b8460000361367857506000613773565b6000808461368785600461461d565b613691919061461d565b9050806000036136ab57670de0b6b3a7640000915061372f565b85816136b7828261461d565b6136c19190614697565b03613704576136fd6ec097ce7bc90715b34b9f1000000000886136e4898561461d565b6136ee9190614697565b6136f891906145f4565b613bfa565b915061372f565b61372c6ec097ce7bc90715b34b9f1000000000876137228a85614697565b6136ee919061461d565b91505b6000670de0b6b3a76400006137576137478286614655565b61375288600261461d565b612d5c565b61376191906145f4565b905061376d8882612d36565b93505050505b949350505050565b6000610bcd826ec097ce7bc90715b34b9f1000000000614697565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526137e8908490613ce2565b505050565b600080861161382f5760405162461bcd60e51b815260206004820152600e60248201526d5441524745545f49535f5a45524f60901b60448201526064016108db565b8360000361383f57506000613af6565b8160000361386f57846138528486612d36565b11613866576138618385612d36565b613868565b845b9050613af6565b670de0b6b3a7640000820361393b5760008061388b868661461d565b90508060000361389e576000915061390c565b86816138aa828261461d565b6138b49190614697565b036138de576138c3888061461d565b6138cd888361461d565b6138d79190614697565b915061390c565b8785816138eb8a8a61461d565b6138f59190614697565b6138ff919061461d565b6139099190614697565b91505b61391e670de0b6b3a7640000836145f4565b613928838961461d565b6139329190614697565b92505050613af6565b6000613947858561461d565b8787613953828761461d565b61395d9190614697565b613967919061461d565b61397191906145f4565b905060008661398885670de0b6b3a7640000614655565b613992919061461d565b905060008282106139b2576139a78383614655565b9150600090506139c3565b6139bc8284614655565b9150600190505b6139d5670de0b6b3a764000083614697565b91506000613a136139ee87670de0b6b3a7640000614655565b6139f990600461461d565b8b613a04898e612d36565b613a0e919061461d565b612d36565b9050613a23816136ee858061461d565b90506000613a3987670de0b6b3a7640000614655565b613a4490600261461d565b905060008315613aaf57613a588584614655565b905080600003613aaa5760405162461bcd60e51b815260206004820152601960248201527f444f444f4d6174683a2073686f756c64206e6f7420626520300000000000000060448201526064016108db565b613abc565b613ab983866145f4565b90505b6000613ac88284613db7565b90508b811115613ae2576000975050505050505050613af6565b613aec818d614655565b9750505050505050505b95945050505050565b6000808611613b415760405162461bcd60e51b815260206004820152600e60248201526d5441524745545f49535f5a45524f60901b60448201526064016108db565b6000613b4d8587614655565b613b57908561461d565b905082600003613b7b57613b73670de0b6b3a764000082614697565b915050613af6565b6000613b9b87613b8b8a8061461d565b613b959190614697565b87612d5c565b90506000613ba98583612d36565b90506ec097ce7bc90715b34b9f10000000008382613bcf88670de0b6b3a7640000614655565b613bd991906145f4565b613be3919061461d565b613bed9190614697565b9998505050505050505050565b600081600003613c0c57506000919050565b60006001613c1984613dd4565b901c6001901b90506001818481613c3257613c32614681565b048201901c90506001818481613c4a57613c4a614681565b048201901c90506001818481613c6257613c62614681565b048201901c90506001818481613c7a57613c7a614681565b048201901c90506001818481613c9257613c92614681565b048201901c90506001818481613caa57613caa614681565b048201901c90506001818481613cc257613cc2614681565b048201901c9050612d5581828581613cdc57613cdc614681565b04613e68565b6000613d37826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e7e9092919063ffffffff16565b9050805160001480613d58575080806020019051810190613d5891906147e5565b6137e85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108db565b6000612d55613dce84670de0b6b3a764000061461d565b8361317c565b600080608083901c15613de957608092831c92015b604083901c15613dfb57604092831c92015b602083901c15613e0d57602092831c92015b601083901c15613e1f57601092831c92015b600883901c15613e3157600892831c92015b600483901c15613e4357600492831c92015b600283901c15613e5557600292831c92015b600183901c15610bcd5760010192915050565b6000818310613e775781612d55565b5090919050565b6060613773848460008585600080866001600160a01b03168587604051613ea59190614802565b60006040518083038185875af1925050503d8060008114613ee2576040519150601f19603f3d011682016040523d82523d6000602084013e613ee7565b606091505b5091509150613ef887838387613f03565b979650505050505050565b60608315613f72578251600003613f6b576001600160a01b0385163b613f6b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108db565b5081613773565b6137738383815115613f875781518083602001fd5b8060405162461bcd60e51b81526004016108db91906140c7565b6040518060e0016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160006002811115613fe957613fe961417b565b905290565b80356001600160a01b0381168114611f5057600080fd5b801515811461317957600080fd5b60008060008060008060008060006101208a8c03121561403257600080fd5b61403b8a613fee565b985061404960208b01613fee565b975061405760408b01613fee565b965061406560608b01613fee565b955060808a0135945060a08a0135935060c08a0135925060e08a013591506101008a013561409281614005565b809150509295985092959850929598565b60005b838110156140be5781810151838201526020016140a6565b50506000910152565b60208152600082518060208401526140e68160408501602087016140a3565b601f01601f19169190910160400192915050565b6000806040838503121561410d57600080fd5b61411683613fee565b946020939093013593505050565b60006020828403121561413657600080fd5b612d5582613fee565b60008060006060848603121561415457600080fd5b61415d84613fee565b925061416b60208501613fee565b9150604084013590509250925092565b634e487b7160e01b600052602160045260246000fd5b600381106141af57634e487b7160e01b600052602160045260246000fd5b9052565b84815260208101849052608081016141ce6040830185614191565b82606083015295945050505050565b6000602082840312156141ef57600080fd5b5035919050565b600060e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015161424660c0840182614191565b5092915050565b60008083601f84011261425f57600080fd5b50813567ffffffffffffffff81111561427757600080fd5b602083019150836020828501011115612fd457600080fd5b600080600080600080600060c0888a0312156142aa57600080fd5b873596506142ba60208901613fee565b95506040880135945060608801359350608088013567ffffffffffffffff8111156142e457600080fd5b6142f08a828b0161424d565b989b979a5095989497959660a090950135949350505050565b60008060008060006080868803121561432157600080fd5b853594506020860135935061433860408701613fee565b9250606086013567ffffffffffffffff81111561435457600080fd5b6143608882890161424d565b969995985093965092949392505050565b60ff8116811461317957600080fd5b600080600080600080600060e0888a03121561439b57600080fd5b6143a488613fee565b96506143b260208901613fee565b9550604088013594506060880135935060808801356143d081614371565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561440057600080fd5b61440983613fee565b915061441760208401613fee565b90509250929050565b600084516144328184602089016140a3565b8451908301906144468183602089016140a3565b84519101906144598183602088016140a3565b0195945050505050565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061448d57607f821691505b6020821081036144ad57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156137e857600081815260208120601f850160051c810160208610156144da5750805b601f850160051c820191505b818110156144f9578281556001016144e6565b505050505050565b815167ffffffffffffffff81111561451b5761451b614463565b61452f816145298454614479565b846144b3565b602080601f831160018114614564576000841561454c5750858301515b600019600386901b1c1916600185901b1785556144f9565b600085815260208120601f198616915b8281101561459357888601518255948401946001909101908401614574565b50858210156145b15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156145d357600080fd5b8151612d5581614371565b634e487b7160e01b600052601160045260246000fd5b80820180821115610bcd57610bcd6145de565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615614637576146376145de565b500290565b60006001820161464e5761464e6145de565b5060010190565b81810381811115610bcd57610bcd6145de565b60006020828403121561467a57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826146b457634e487b7160e01b600052601260045260246000fd5b500490565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015284604082015283606082015260a06080820152600061471660a0830184866146b9565b98975050505050505050565b6020808252600890820152674f564552464c4f5760c01b604082015260600190565b60208101610bcd8284614191565b6001600160a01b0396871681529486166020860152604085019390935260608401919091528316608083015290911660a082015260c00190565b60018060a01b0386168152846020820152836040820152608060608201526000613ef86080830184866146b9565b60208082526011908201527011931054d217d313d05397d19052531151607a1b604082015260600190565b6000602082840312156147f757600080fd5b8151612d5581614005565b600082516148148184602087016140a3565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efdf176ad18be4f9f32efaa32f06e9d1175476504739a745f1399a6d3fa4b75917c2c0245e056d5fb095f04cd6373bc770802ebd1e6c918eb78fdef843cdb37b0fa2646970667358221220f3687e01d102b5cdb36d7d8bacce721c475ea34f78cb33a0180d425c383b574c64736f6c63430008100033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061038e5760003560e01c8063880a4d87116101de578063d505accf1161010f578063ee27c689116100ad578063fcf709f71161007c578063fcf709f714610841578063fd1ed7e91461084c578063fe24cb7f14610889578063fff6cae91461089257600080fd5b8063ee27c68914610815578063f5346aea1461081d578063f6b06e7014610825578063f811d6921461083857600080fd5b8063e539ef49116100e9578063e539ef49146107de578063e6485c8e146107f1578063eb99da6a14610804578063ec2fd46d1461080c57600080fd5b8063d505accf1461077f578063dd62ed3e14610792578063dd93f59a146107cb57600080fd5b8063bbf5ce781161017c578063bfdbd72311610156578063bfdbd72314610747578063c0ffa17814610750578063d0a494e414610759578063d4b970461461076c57600080fd5b8063bbf5ce7814610703578063bd6015b41461071d578063bf357dae1461073057600080fd5b8063a9059cbb116101b8578063a9059cbb146106c1578063ab44a7a3146106d4578063b56ceaa6146106dd578063b59b8555146106f057600080fd5b8063880a4d871461067857806395d89b41146106a4578063a382d1b9146106ac57600080fd5b806347bbad2e116102c357806370a082311161026157806377f586571161023057806377f586571461060057806379a04876146106325780637d721504146106455780637ecebe001461065857600080fd5b806370a08231146105b457806371f9100c146105dd57806372bf079e146105e557806373d74cf8146105f857600080fd5b806354fd4d501161029d57806354fd4d501461055157806363ab59931461057657806365f6fcbb1461058957806366410a211461059157600080fd5b806347bbad2e146105075780634a248d2a146105105780634c85b4251461052357600080fd5b806330adf81f116103305780633644e5151161030a5780633644e515146104ab5780633afdfeba146104b45780634322ec83146104bd57806344096609146104ee57600080fd5b806330adf81f14610438578063313ce5671461045f57806336223ce91461047e57600080fd5b8063171019401161036c57806317101940146103e957806318160ddd146103fc57806323b872dd146104135780632df6cb481461042657600080fd5b806304b621bc1461039357806306fdde03146103a8578063095ea7b3146103c6575b600080fd5b6103a66103a1366004614013565b61089a565b005b6103b0610b2e565b6040516103bd91906140c7565b60405180910390f35b6103d96103d43660046140fa565b610bbc565b60405190151581526020016103bd565b6103b06103f7366004614124565b610bd3565b610405600b5481565b6040519081526020016103bd565b6103d961042136600461413f565b610d56565b6001546103d990610100900460ff1681565b6104057f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60095461046c9060ff1681565b60405160ff90911681526020016103bd565b6005546001600160701b0380821691600160701b9004165b604080519283526020830191909152016103bd565b610405600e5481565b61040560145481565b6001546104d6906201000090046001600160a01b031681565b6040516001600160a01b0390911681526020016103bd565b6104966104fc366004614124565b506011546010549091565b61040560165481565b6003546104d6906001600160a01b031681565b610536610531366004614124565b610f06565b604080519384526020840192909252908201526060016103bd565b60408051808201909152600981526847535020312e302e3160b81b60208201526103b0565b6002546104d6906001600160a01b031681565b610405611370565b6105a461059f3660046140fa565b611408565b6040516103bd94939291906141b3565b6104056105c2366004614124565b6001600160a01b03166000908152600c602052604090205490565b610405611471565b6103a66105f33660046141dd565b6114bf565b6103a66115a4565b60075461061a90600160701b90046001600160701b031681565b6040516001600160701b0390911681526020016103bd565b6105a46106403660046140fa565b61165b565b60055461061a906001600160701b031681565b610405610666366004614124565b600f6020526000908152604090205481565b60055461068f90600160e01b900463ffffffff1681565b60405163ffffffff90911681526020016103bd565b6103b06116c4565b6106b46116d1565b6040516103bd91906141f6565b6103d96106cf3660046140fa565b611773565b61040560115481565b6104966106eb36600461428f565b61185f565b6103a66106fe3660046141dd565b611c39565b60055461061a90600160701b90046001600160701b031681565b61040561072b366004614124565b611cdc565b60075461068f90600160e01b900463ffffffff1681565b61040560155481565b61040560105481565b6103a6610767366004614309565b611f55565b6004546104d6906001600160a01b031681565b6103a661078d366004614380565b612515565b6104056107a03660046143ed565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205490565b6104056107d9366004614124565b61272b565b60075461061a906001600160701b031681565b6103a66107ff3660046141dd565b612998565b6103a6612a36565b61040560125481565b610405612ae6565b610405612af8565b6017546104d6906001600160a01b031681565b61040560135481565b601554601654610496565b610854612c00565b604080519788526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0016103bd565b61040560065481565b6103a6612c62565b60015460ff16156108e45760405162461bcd60e51b815260206004820152600f60248201526e11d4d417d253925512505312569151608a1b60448201526064015b60405180910390fd5b6001805460ff1916811790556001600160a01b038087169088160361094b5760405162461bcd60e51b815260206004820152601a60248201527f424153455f51554f54455f43414e5f4e4f545f42455f53414d4500000000000060448201526064016108db565b600380546001600160a01b03808a166001600160a01b0319928316179092556004805492891692909116919091179055821580159061099957506ec097ce7bc90715b34b9f10000000008311155b6109a257600080fd5b6013839055670de0b6b3a76400008211156109bc57600080fd5b60128290556011859055601084905560018054600280546001600160a01b038c81166001600160a01b03199092169190911790915561ff0019908c16620100000216610100600160b01b0319909116178155604080518082018252918252605f60f81b6020808401919091528151808301909252600382526204753560ec1b908201528082610a4a30610bd3565b604051602001610a5c93929190614420565b604051602081830303815290604052600a9081610a799190614501565b506040805180820190915260038152620474c560ec1b6020820152600890610aa19082614501565b50886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0491906145c1565b6009805460ff191660ff92909216919091179055610b20612af8565b505050505050505050505050565b600a8054610b3b90614479565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6790614479565b8015610bb45780601f10610b8957610100808354040283529160200191610bb4565b820191906000526020600020905b815481529060010190602001808311610b9757829003601f168201915b505050505081565b6000610bc9338484612c7c565b5060015b92915050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b6020820152815160088082528184019093526060926001600160a01b038516929160009160208201818036833701905050905060005b6004811015610d4d5782600485610c4284600c6145f4565b60208110610c5257610c52614607565b1a60f81b6001600160f81b031916901c60f81c60ff1681518110610c7857610c78614607565b01602001516001600160f81b03191682610c9383600261461d565b81518110610ca357610ca3614607565b60200101906001600160f81b031916908160001a9053508284610cc783600c6145f4565b60208110610cd757610cd7614607565b825191901a600f16908110610cee57610cee614607565b01602001516001600160f81b03191682610d0983600261461d565b610d149060016145f4565b81518110610d2457610d24614607565b60200101906001600160f81b031916908160001a90535080610d458161463c565b915050610c2a565b50949350505050565b6001600160a01b0383166000908152600c6020526040812054821115610db35760405162461bcd60e51b81526020600482015260126024820152710848298829c868abe9c9ea8be8a9c9eaa8e960731b60448201526064016108db565b6001600160a01b0384166000908152600d60209081526040808320338452909152902054821115610e1d5760405162461bcd60e51b815260206004820152601460248201527308298989eae829c868abe9c9ea8be8a9c9eaa8e960631b60448201526064016108db565b6001600160a01b0384166000908152600c6020526040902054610e41908390614655565b6001600160a01b038086166000908152600c60205260408082209390935590851681522054610e719083906145f4565b6001600160a01b038085166000908152600c60209081526040808320949094559187168152600d82528281203382529091522054610eb0908390614655565b6001600160a01b038581166000818152600d60209081526040808320338452825291829020949094555185815291861692909160008051602061481f833981519152910160405180910390a35060019392505050565b6000806000610f13612cdd565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015610f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f849190614668565b610f8e9190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110049190614668565b61100e9190614655565b6005549091506001600160701b0380821691600160701b9004166110328285614655565b955061103e8184614655565b9450600086116110805760405162461bcd60e51b815260206004820152600d60248201526c1393d7d09054d157d253941555609a1b60448201526064016108db565b600b546000036111f957600083116110ce5760405162461bcd60e51b815260206004820152601160248201527016915493d7d45553d51157d05353d55395607a1b60448201526064016108db565b6110da84601354612d36565b83106110e657836110f2565b6110f283601354612d5c565b600780546001600160701b0319166001600160701b03831617905560135490975061111e908890612d36565b60078054600160701b600160e01b031916600160701b6001600160701b039384168102919091179182905590041661118f5760405162461bcd60e51b815260206004820152601460248201527351554f54455f5441524745545f49535f5a45524f60601b60448201526064016108db565b6107d187116111d95760405162461bcd60e51b815260206004820152601660248201527509a929ca8be829a9eaa9ca8be9c9ea8be8a9c9eaa8e960531b60448201526064016108db565b6111e660006103e9612d71565b6111f26103e988614655565b96506112f0565b6000821180156112095750600081115b156112f057600061121a8784612d5c565b905060006112288784612d5c565b90506000828210611239578261123b565b815b9050611249600b5482612d36565b600754909a50611262906001600160701b031682612d36565b60075461127891906001600160701b03166145f4565b600780546001600160701b0319166001600160701b0392831617908190556112a991600160701b9091041682612d36565b6007546112c69190600160701b90046001600160701b03166145f4565b6007600e6101000a8154816001600160701b0302191690836001600160701b031602179055505050505b6112fa8888612d71565b6113048484612e7b565b6001600160a01b0388166000818152600c60209081526040918290205482519384529083018a905282820152517f1c172440bdebb59cd92a7f08f4227903a3305ab6f880cb25f93eddb66843a1029181900360600190a1505050506113696001600055565b9193909250565b6015546005546003546040516370a0823160e01b8152306004820152600093926001600160701b0316916001600160a01b0316906370a08231906024015b602060405180830381865afa1580156113cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ef9190614668565b6113f99190614655565b6114039190614655565b905090565b60008060008060006114186116d1565b90506114248187612ee6565b6011546010549297509094509061143b8782612d36565b9550856114488884612d36565b6114529089614655565b61145c9190614655565b96508260a00151935050505092959194509250565b601654600554600480546040516370a0823160e01b8152309281019290925260009392600160701b90046001600160701b0316916001600160a01b03909116906370a08231906024016113ae565b6002546001600160a01b0316331461150f5760405162461bcd60e51b8152602060048201526013602482015272105113525397d050d0d154d4d7d11153925151606a1b60448201526064016108db565b6000601354821161152d57816013546115289190614655565b61153a565b60135461153a9083614655565b905060145460135482620f4240611551919061461d565b61155b9190614697565b111561159e5760405162461bcd60e51b8152602060048201526012602482015271115610d1515117d4149250d157d31253525560721b60448201526064016108db565b50601355565b60075463ffffffff600160e01b9091041660021480156115d457506007546005546001600160701b039182169116105b156115f957600554600160701b8082046001600160701b039081169091029116176007555b60075463ffffffff600160e01b90910416600114801561163457506007546005546001600160701b03600160701b9283900481169290910416105b1561165957600554600160701b8082046001600160701b039081169091029116176007555b565b600080600080600061166b6116d1565b90506116778187612fdb565b6011546010549297509094509061168e8782612d36565b95508561169b8884612d36565b6116a59089614655565b6116af9190614655565b96508260800151935050505092959194509250565b60088054610b3b90614479565b6116d9613fa1565b601354815260125460208201526005546001600160701b038082166040840152600160701b918290048116606084015260075480821660808501529182041660a0830152600160e01b900463ffffffff16600281111561173b5761173b61417b565b8160c0019060028111156117515761175161417b565b908160028111156117645761176461417b565b905250611770816130d8565b90565b336000908152600c60205260408120548211156117c75760405162461bcd60e51b81526020600482015260126024820152710848298829c868abe9c9ea8be8a9c9eaa8e960731b60448201526064016108db565b336000908152600c60205260409020546117e2908390614655565b336000908152600c6020526040808220929092556001600160a01b0385168152205461180f9083906145f4565b6001600160a01b0384166000818152600c602052604090819020929092559051339060008051602061481f8339815191529061184e9086815260200190565b60405180910390a350600192915050565b60008061186a612cdd565b428310156118a95760405162461bcd60e51b815260206004820152600c60248201526b1512535157d156141254915160a21b60448201526064016108db565b336000908152600c60205260409020548911156118f95760405162461bcd60e51b815260206004820152600e60248201526d08e98a0be9c9ea8be8a9c9eaa8e960931b60448201526064016108db565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015611946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196a9190614668565b6119749190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa1580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614668565b6119f49190614655565b600b5490915080611a058d8561461d565b611a0f9190614697565b945080611a1c8d8461461d565b611a269190614697565b600754909450611a4a90611a44908e906001600160701b031661461d565b8261317c565b600754611a6091906001600160701b0316614655565b600780546001600160701b0319166001600160701b039283161790819055611a9691611a44918f91600160701b9091041661461d565b600754611ab39190600160701b90046001600160701b0316614655565b6007600e6101000a8154816001600160701b0302191690836001600160701b03160217905550898510158015611ae95750888410155b611b2b5760405162461bcd60e51b81526020600482015260136024820152720ae92a89088a482aebe9c9ea8be8a9c9eaa8e9606b1b60448201526064016108db565b611b35338d6131c5565b611b3f8b8661327d565b611b498b8561329e565b611b516132bb565b8615611bc0578a6001600160a01b0316632411d338338e88888d8d6040518763ffffffff1660e01b8152600401611b8d969594939291906146e2565b600060405180830381600087803b158015611ba757600080fd5b505af1158015611bbb573d6000803e3d6000fd5b505050505b336000818152600c60209081526040918290205482519384526001600160a01b038f16918401919091528282018f90526060830152517f55caccde83781f39bfc1296eff45655b6496729443a7d48958b18b3b685600a59181900360800190a1505050611c2d6001600055565b97509795505050505050565b6001546201000090046001600160a01b03163314611c895760405162461bcd60e51b815260206004820152600d60248201526c1050d0d154d4d7d11153925151609a1b60448201526064016108db565b670de0b6b3a7640000811115611cd75760405162461bcd60e51b8152602060048201526013602482015272494e56414c49445f4d545f4645455f5241544560681b60448201526064016108db565b601055565b6000611ce6612cdd565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015611d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d579190614668565b611d619190614655565b600554909150600090611d7d906001600160701b031683614655565b90506000806000611d8e328561165b565b9298509094509092509050611da3878761329e565b82601654611db191906145f4565b601655806002811115611dc657611dc661417b565b600754600160e01b900463ffffffff908116911614611e79576001600160701b03821115611e065760405162461bcd60e51b81526004016108db90614722565b600780546001600160701b0319166001600160701b038416179055806002811115611e3357611e3361417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f83398151915281604051611e709190614744565b60405180910390a15b601654600480546040516370a0823160e01b81523092810192909252611f0092889290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef19190614668565b611efb9190614655565b612e7b565b60035460045460405160008051602061485f83398151915292611f39926001600160a01b039182169291169088908b9033908e90614752565b60405180910390a15050505050611f506001600055565b919050565b611f5d612cdd565b611f67838661327d565b611f71838561329e565b8015611fde5760405163d5b9979760e01b81526001600160a01b0384169063d5b9979790611fab903390899089908890889060040161478c565b600060405180830381600087803b158015611fc557600080fd5b505af1158015611fd9573d6000803e3d6000fd5b505050505b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa15801561202b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204f9190614668565b6120599190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa1580156120ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cf9190614668565b6120d99190614655565b6005549091506001600160701b0316821015806121085750600554600160701b90046001600160701b03168110155b6121245760405162461bcd60e51b81526004016108db906147ba565b6005546001600160701b03168210156122e85760055460009061215790600160701b90046001600160701b031683614655565b90506000806000806121693286611408565b60055493975091955093509150849061218c9089906001600160701b0316614655565b11156121aa5760405162461bcd60e51b81526004016108db906147ba565b826015546121b891906145f4565b6015558160028111156121cd576121cd61417b565b600754600160e01b900463ffffffff908116911614612289576001600160701b0381111561220d5760405162461bcd60e51b81526004016108db90614722565b60078054600160701b600160e01b031916600160701b6001600160701b038416021790558160028111156122435761224361417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f833981519152826040516122809190614744565b60405180910390a15b60008051602061485f833981519152600460009054906101000a90046001600160a01b0316600360009054906101000a90046001600160a01b03168787338f6040516122da96959493929190614752565b60405180910390a150505050505b600554600160701b90046001600160701b03168110156124aa5760055460009061231b906001600160701b031684614655565b905060008060008061232d328661165b565b600554939750919550935091508490612357908890600160701b90046001600160701b0316614655565b11156123755760405162461bcd60e51b81526004016108db906147ba565b8260165461238391906145f4565b6016558160028111156123985761239861417b565b600754600160e01b900463ffffffff90811691161461244b576001600160701b038111156123d85760405162461bcd60e51b81526004016108db90614722565b600780546001600160701b0319166001600160701b0383161790558160028111156124055761240561417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f833981519152826040516124429190614744565b60405180910390a15b60008051602061485f833981519152600360009054906101000a90046001600160a01b0316600460009054906101000a90046001600160a01b03168787338f60405161249c96959493929190614752565b60405180910390a150505050505b6124b26132bb565b604080513381526001600160a01b0387166020820152908101889052606081018790527f0b82e93068db15abd9fbb2682c65462ea8a0a10582dce93a5664818e296f54eb9060800160405180910390a1505061250e6001600055565b5050505050565b4284101561255c5760405162461bcd60e51b81526020600482015260146024820152731113d113d7d1d4d417d3140e881156141254915160621b60448201526064016108db565b600e546001600160a01b0388166000908152600f6020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9190876125af8361463c565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161262892919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612693573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906126c95750886001600160a01b0316816001600160a01b0316145b6127155760405162461bcd60e51b815260206004820152601e60248201527f444f444f5f4753505f4c503a20494e56414c49445f5349474e4154555245000060448201526064016108db565b612720898989612c7c565b505050505050505050565b6000612735612cdd565b601654600480546040516370a0823160e01b81523092810192909252600092916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ab9190614668565b6127b59190614655565b6005549091506000906127d890600160701b90046001600160701b031683614655565b905060008060006127e93285611408565b92985090945090925090506127fe878761327d565b8260155461280c91906145f4565b6015558060028111156128215761282161417b565b600754600160e01b900463ffffffff9081169116146128dd576001600160701b038211156128615760405162461bcd60e51b81526004016108db90614722565b60078054600160701b600160e01b031916600160701b6001600160701b038516021790558060028111156128975761289761417b565b6007601c6101000a81548163ffffffff021916908363ffffffff16021790555060008051602061483f833981519152816040516128d49190614744565b60405180910390a15b6015546003546040516370a0823160e01b815230600482015261295f92916001600160a01b0316906370a0823190602401602060405180830381865afa15801561292b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294f9190614668565b6129599190614655565b86612e7b565b60045460035460405160008051602061485f83398151915292611f39926001600160a01b039182169291169088908b9033908e90614752565b6002546001600160a01b031633146129e85760405162461bcd60e51b8152602060048201526013602482015272105113525397d050d0d154d4d7d11153925151606a1b60448201526064016108db565b620f4240811115612a315760405162461bcd60e51b81526020600482015260136024820152721253959053125117d4149250d157d312535255606a1b60448201526064016108db565b601455565b612a3e612cdd565b6001546201000090046001600160a01b03163314612a8e5760405162461bcd60e51b815260206004820152600d60248201526c1050d0d154d4d7d11153925151609a1b60448201526064016108db565b601680546015546000909255600154909190612ab9906201000090046001600160a01b03168361329e565b6000601555600154612ada906201000090046001600160a01b03168261327d565b50506116596001600055565b6000611403612af36116d1565b613463565b60408051808201825260018152605f60f81b6020808301919091528251808401909352600383526204753560ec1b90830152600091828183612b3930610bd3565b604051602001612b4b93929190614420565b60408051601f198184030181528282528051602091820120838301835260018452603160f81b9382019390935281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81830152808301939093527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608401524660808401523060a0808501919091528251808503909101815260c09093019091528151910120600e819055949350505050565b600080600080600080600080612c146116d1565b905080600001519750806020015196508060400151955080606001519450806080015193508060a0015192508060c001516002811115612c5657612c5661417b565b91505090919293949596565b612c6a612cdd565b612c726132bb565b6116596001600055565b6001600160a01b038381166000818152600d602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600260005403612d2f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108db565b6002600055565b6000670de0b6b3a7640000612d4b838561461d565b612d559190614697565b9392505050565b600081612d4b84670de0b6b3a764000061461d565b6103e88111612dbb5760405162461bcd60e51b815260206004820152601660248201527509a929ca8be829a9eaa9ca8be9c9ea8be8a9c9eaa8e960531b60448201526064016108db565b6001600160a01b0382166000908152600c6020526040902054612ddf9082906145f4565b6001600160a01b0383166000908152600c6020526040902055600b54612e069082906145f4565b600b556040518181526001600160a01b038316907f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968859060200160405180910390a26040518181526001600160a01b0383169060009060008051602061481f833981519152906020015b60405180910390a35050565b6001600160701b038211801590612e9957506001600160701b038111155b612eb55760405162461bcd60e51b81526004016108db90614722565b600580546001600160701b03928316600160701b026001600160e01b03199091169290931691909117919091179055565b600080808460c001516002811115612f0057612f0061417b565b03612f1a57612f0f8484613562565b915060019050612fd4565b60018460c001516002811115612f3257612f3261417b565b03612f4157612f0f8484613589565b600084606001518560a00151612f579190614655565b9050600085608001518660400151612f6f9190614655565b905081851015612f9a57612f8386866135a6565b93506002925080841115612f95578093505b612fd1565b818503612fad5780935060009250612fd1565b612fc086612fbb8488614655565b613562565b612fca90826145f4565b9350600192505b50505b9250929050565b600080808460c001516002811115612ff557612ff561417b565b0361300f5761300484846135da565b915060029050612fd4565b60018460c0015160028111156130275761302761417b565b036130c3576000846040015185608001516130429190614655565b905060008560a00151866060015161305a9190614655565b9050818510156130855761306e86866135f9565b93506001925080841115613080578093505b6130bc565b81850361309857809350600092506130bc565b6130ab866130a68488614655565b6135da565b6130b590826145f4565b9350600292505b5050612fd4565b6130cd8484613624565b946002945092505050565b60028160c0015160028111156130f0576130f061417b565b036131255761311d8160600151826080015183604001516131119190614655565b83516020850151613643565b60a082015250565b60018160c00151600281111561313d5761313d61417b565b036131795761317381604001518260a00151836060015161315e9190614655565b83516131699061377b565b8460200151613643565b60808201525b50565b6000806131898385614697565b90506000613197848361461d565b6131a19086614655565b905080156131bd576131b48260016145f4565b92505050610bcd565b509050610bcd565b6001600160a01b0382166000908152600c60205260409020546131e9908290614655565b6001600160a01b0383166000908152600c6020526040902055600b54613210908290614655565b600b556040518181526001600160a01b038316907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59060200160405180910390a26040518181526000906001600160a01b0384169060008051602061481f83398151915290602001612e6f565b801561329a5760035461329a906001600160a01b03168383613796565b5050565b801561329a5760045461329a906001600160a01b03168383613796565b6015546003546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015613308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332c9190614668565b6133369190614655565b601654600480546040516370a0823160e01b815230928101929092529293506000926001600160a01b0316906370a0823190602401602060405180830381865afa158015613388573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ac9190614668565b6133b69190614655565b90506001600160701b0382118015906133d657506001600160701b038111155b6133f25760405162461bcd60e51b81526004016108db90614722565b6005546001600160701b0316821461342057600580546001600160701b0319166001600160701b0384161790555b600554600160701b90046001600160701b0316811461329a57600580546001600160701b038316600160701b02600160701b600160e01b03199091161790555050565b600060028260c00151600281111561347d5761347d61417b565b036134f257606082015160a08301516000916134b19161349d908061461d565b6134a79190614697565b8460600151612d5c565b90506134c1836020015182612d36565b60208401516134d890670de0b6b3a7640000614655565b6134e291906145f4565b9050612d55836000015182612d5c565b604082015160808301516000916135219161350d908061461d565b6135179190614697565b8460400151612d5c565b9050613531836020015182612d36565b602084015161354890670de0b6b3a7640000614655565b61355291906145f4565b9050612d55836000015182612d36565b6000612d55836080015184608001518461357f876000015161377b565b87602001516137ed565b6000612d55836080015184604001518461357f876000015161377b565b6000612d558360a001518385606001516135c091906145f4565b606086015186516135d09061377b565b8760200151613aff565b6000612d558360a001518460a0015184866000015187602001516137ed565b6000612d55836080015183856040015161361391906145f4565b604086015186516020880151613aff565b6000612d558360a00151846060015184866000015187602001516137ed565b600081600003613668576136578385612d36565b61366190866145f4565b9050613773565b8460000361367857506000613773565b6000808461368785600461461d565b613691919061461d565b9050806000036136ab57670de0b6b3a7640000915061372f565b85816136b7828261461d565b6136c19190614697565b03613704576136fd6ec097ce7bc90715b34b9f1000000000886136e4898561461d565b6136ee9190614697565b6136f891906145f4565b613bfa565b915061372f565b61372c6ec097ce7bc90715b34b9f1000000000876137228a85614697565b6136ee919061461d565b91505b6000670de0b6b3a76400006137576137478286614655565b61375288600261461d565b612d5c565b61376191906145f4565b905061376d8882612d36565b93505050505b949350505050565b6000610bcd826ec097ce7bc90715b34b9f1000000000614697565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526137e8908490613ce2565b505050565b600080861161382f5760405162461bcd60e51b815260206004820152600e60248201526d5441524745545f49535f5a45524f60901b60448201526064016108db565b8360000361383f57506000613af6565b8160000361386f57846138528486612d36565b11613866576138618385612d36565b613868565b845b9050613af6565b670de0b6b3a7640000820361393b5760008061388b868661461d565b90508060000361389e576000915061390c565b86816138aa828261461d565b6138b49190614697565b036138de576138c3888061461d565b6138cd888361461d565b6138d79190614697565b915061390c565b8785816138eb8a8a61461d565b6138f59190614697565b6138ff919061461d565b6139099190614697565b91505b61391e670de0b6b3a7640000836145f4565b613928838961461d565b6139329190614697565b92505050613af6565b6000613947858561461d565b8787613953828761461d565b61395d9190614697565b613967919061461d565b61397191906145f4565b905060008661398885670de0b6b3a7640000614655565b613992919061461d565b905060008282106139b2576139a78383614655565b9150600090506139c3565b6139bc8284614655565b9150600190505b6139d5670de0b6b3a764000083614697565b91506000613a136139ee87670de0b6b3a7640000614655565b6139f990600461461d565b8b613a04898e612d36565b613a0e919061461d565b612d36565b9050613a23816136ee858061461d565b90506000613a3987670de0b6b3a7640000614655565b613a4490600261461d565b905060008315613aaf57613a588584614655565b905080600003613aaa5760405162461bcd60e51b815260206004820152601960248201527f444f444f4d6174683a2073686f756c64206e6f7420626520300000000000000060448201526064016108db565b613abc565b613ab983866145f4565b90505b6000613ac88284613db7565b90508b811115613ae2576000975050505050505050613af6565b613aec818d614655565b9750505050505050505b95945050505050565b6000808611613b415760405162461bcd60e51b815260206004820152600e60248201526d5441524745545f49535f5a45524f60901b60448201526064016108db565b6000613b4d8587614655565b613b57908561461d565b905082600003613b7b57613b73670de0b6b3a764000082614697565b915050613af6565b6000613b9b87613b8b8a8061461d565b613b959190614697565b87612d5c565b90506000613ba98583612d36565b90506ec097ce7bc90715b34b9f10000000008382613bcf88670de0b6b3a7640000614655565b613bd991906145f4565b613be3919061461d565b613bed9190614697565b9998505050505050505050565b600081600003613c0c57506000919050565b60006001613c1984613dd4565b901c6001901b90506001818481613c3257613c32614681565b048201901c90506001818481613c4a57613c4a614681565b048201901c90506001818481613c6257613c62614681565b048201901c90506001818481613c7a57613c7a614681565b048201901c90506001818481613c9257613c92614681565b048201901c90506001818481613caa57613caa614681565b048201901c90506001818481613cc257613cc2614681565b048201901c9050612d5581828581613cdc57613cdc614681565b04613e68565b6000613d37826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e7e9092919063ffffffff16565b9050805160001480613d58575080806020019051810190613d5891906147e5565b6137e85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108db565b6000612d55613dce84670de0b6b3a764000061461d565b8361317c565b600080608083901c15613de957608092831c92015b604083901c15613dfb57604092831c92015b602083901c15613e0d57602092831c92015b601083901c15613e1f57601092831c92015b600883901c15613e3157600892831c92015b600483901c15613e4357600492831c92015b600283901c15613e5557600292831c92015b600183901c15610bcd5760010192915050565b6000818310613e775781612d55565b5090919050565b6060613773848460008585600080866001600160a01b03168587604051613ea59190614802565b60006040518083038185875af1925050503d8060008114613ee2576040519150601f19603f3d011682016040523d82523d6000602084013e613ee7565b606091505b5091509150613ef887838387613f03565b979650505050505050565b60608315613f72578251600003613f6b576001600160a01b0385163b613f6b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108db565b5081613773565b6137738383815115613f875781518083602001fd5b8060405162461bcd60e51b81526004016108db91906140c7565b6040518060e0016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160006002811115613fe957613fe961417b565b905290565b80356001600160a01b0381168114611f5057600080fd5b801515811461317957600080fd5b60008060008060008060008060006101208a8c03121561403257600080fd5b61403b8a613fee565b985061404960208b01613fee565b975061405760408b01613fee565b965061406560608b01613fee565b955060808a0135945060a08a0135935060c08a0135925060e08a013591506101008a013561409281614005565b809150509295985092959850929598565b60005b838110156140be5781810151838201526020016140a6565b50506000910152565b60208152600082518060208401526140e68160408501602087016140a3565b601f01601f19169190910160400192915050565b6000806040838503121561410d57600080fd5b61411683613fee565b946020939093013593505050565b60006020828403121561413657600080fd5b612d5582613fee565b60008060006060848603121561415457600080fd5b61415d84613fee565b925061416b60208501613fee565b9150604084013590509250925092565b634e487b7160e01b600052602160045260246000fd5b600381106141af57634e487b7160e01b600052602160045260246000fd5b9052565b84815260208101849052608081016141ce6040830185614191565b82606083015295945050505050565b6000602082840312156141ef57600080fd5b5035919050565b600060e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015161424660c0840182614191565b5092915050565b60008083601f84011261425f57600080fd5b50813567ffffffffffffffff81111561427757600080fd5b602083019150836020828501011115612fd457600080fd5b600080600080600080600060c0888a0312156142aa57600080fd5b873596506142ba60208901613fee565b95506040880135945060608801359350608088013567ffffffffffffffff8111156142e457600080fd5b6142f08a828b0161424d565b989b979a5095989497959660a090950135949350505050565b60008060008060006080868803121561432157600080fd5b853594506020860135935061433860408701613fee565b9250606086013567ffffffffffffffff81111561435457600080fd5b6143608882890161424d565b969995985093965092949392505050565b60ff8116811461317957600080fd5b600080600080600080600060e0888a03121561439b57600080fd5b6143a488613fee565b96506143b260208901613fee565b9550604088013594506060880135935060808801356143d081614371565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561440057600080fd5b61440983613fee565b915061441760208401613fee565b90509250929050565b600084516144328184602089016140a3565b8451908301906144468183602089016140a3565b84519101906144598183602088016140a3565b0195945050505050565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061448d57607f821691505b6020821081036144ad57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156137e857600081815260208120601f850160051c810160208610156144da5750805b601f850160051c820191505b818110156144f9578281556001016144e6565b505050505050565b815167ffffffffffffffff81111561451b5761451b614463565b61452f816145298454614479565b846144b3565b602080601f831160018114614564576000841561454c5750858301515b600019600386901b1c1916600185901b1785556144f9565b600085815260208120601f198616915b8281101561459357888601518255948401946001909101908401614574565b50858210156145b15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156145d357600080fd5b8151612d5581614371565b634e487b7160e01b600052601160045260246000fd5b80820180821115610bcd57610bcd6145de565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615614637576146376145de565b500290565b60006001820161464e5761464e6145de565b5060010190565b81810381811115610bcd57610bcd6145de565b60006020828403121561467a57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826146b457634e487b7160e01b600052601260045260246000fd5b500490565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015284604082015283606082015260a06080820152600061471660a0830184866146b9565b98975050505050505050565b6020808252600890820152674f564552464c4f5760c01b604082015260600190565b60208101610bcd8284614191565b6001600160a01b0396871681529486166020860152604085019390935260608401919091528316608083015290911660a082015260c00190565b60018060a01b0386168152846020820152836040820152608060608201526000613ef86080830184866146b9565b60208082526011908201527011931054d217d313d05397d19052531151607a1b604082015260600190565b6000602082840312156147f757600080fd5b8151612d5581614005565b600082516148148184602087016140a3565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efdf176ad18be4f9f32efaa32f06e9d1175476504739a745f1399a6d3fa4b75917c2c0245e056d5fb095f04cd6373bc770802ebd1e6c918eb78fdef843cdb37b0fa2646970667358221220f3687e01d102b5cdb36d7d8bacce721c475ea34f78cb33a0180d425c383b574c64736f6c63430008100033

Deployed Bytecode Sourcemap

91652:4742:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92391:2083;;;;;;:::i;:::-;;:::i;:::-;;57704:18;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70504:150;;;;;;:::i;:::-;;:::i;:::-;;;2215:14:1;;2208:22;2190:41;;2178:2;2163:18;70504:150:0;2050:187:1;95660:460:0;;;;;;:::i;:::-;;:::i;57783:26::-;;;;;;;;;2579:25:1;;;2567:2;2552:18;57783:26:0;2433:177:1;69738:516:0;;;;;;:::i;:::-;;:::i;56496:34::-;;;;;;;;;;;;58248:117;;58299:66;58248:117;;57637:21;;;;;;;;;;;;3302:4:1;3290:17;;;3272:36;;3260:2;3245:18;57637:21:0;3130:184:1;62469:181:0;62587:14;;-1:-1:-1;;;;;62587:14:0;;;;-1:-1:-1;;;62627:15:0;;;62469:181;;;;3493:25:1;;;3549:2;3534:18;;3527:34;;;;3466:18;62469:181:0;3319:248:1;58105:31:0;;;;;;58784:34;;;;;;56636:27;;;;;;;;-1:-1:-1;;;;;56636:27:0;;;;;;-1:-1:-1;;;;;3736:32:1;;;3718:51;;3706:2;3691:18;56636:27:0;3572:203:1;62885:215:0;;;;;;:::i;:::-;-1:-1:-1;63043:13:0;;63079;;63043;;62885:215;59021:29;;;;;;56790:26;;;;;-1:-1:-1;;;;;56790:26:0;;;85298:2876;;;;;;:::i;:::-;;:::i;:::-;;;;4203:25:1;;;4259:2;4244:18;;4237:34;;;;4287:18;;;4280:34;4191:2;4176:18;85298:2876:0;4001:319:1;96297:94:0;96365:18;;;;;;;;;;;;-1:-1:-1;;;96365:18:0;;;;96297:94;;56700:22;;;;;-1:-1:-1;;;;;56700:22:0;;;63399:174;;;:::i;83614:764::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;69328:115::-;;;;;;:::i;:::-;-1:-1:-1;;;;;69420:15:0;69385;69420;;;:8;:15;;;;;;;69328:115;63834:178;;;:::i;66745:287::-;;;;;;:::i;:::-;;:::i;65574:538::-;;;:::i;57353:29::-;;;;;-1:-1:-1;;;57353:29:0;;-1:-1:-1;;;;;57353:29:0;;;;;;-1:-1:-1;;;;;5466:43:1;;;5448:62;;5436:2;5421:18;57353:29:0;5302:214:1;82358:764:0;;;;;;:::i;:::-;;:::i;56936:29::-;;;;;-1:-1:-1;;;;;56936:29:0;;;58372:41;;;;;;:::i;:::-;;;;;;;;;;;;;;57070:36;;;;;-1:-1:-1;;;57070:36:0;;;;;;;;;5695:10:1;5683:23;;;5665:42;;5653:2;5638:18;57070:36:0;5521:192:1;57563:20:0;;;:::i;59422:407::-;;;:::i;:::-;;;;;;;:::i;68764:332::-;;;;;;:::i;:::-;;:::i;58609:28::-;;;;;;88831:2488;;;;;;:::i;:::-;;:::i;67205:174::-;;;;;;:::i;:::-;;:::i;56972:30::-;;;;;-1:-1:-1;;;56972:30:0;;-1:-1:-1;;;;;56972:30:0;;;75224:1337;;;;;;:::i;:::-;;:::i;57440:22::-;;;;;-1:-1:-1;;;57440:22:0;;;;;;58926:28;;;;;;58526;;;;;;78513:3306;;;;;;:::i;:::-;;:::i;56823:27::-;;;;;-1:-1:-1;;;;;56823:27:0;;;71985:1079;;;;;;:::i;:::-;;:::i;71212:132::-;;;;;;:::i;:::-;-1:-1:-1;;;;;71311:16:0;;;71284:7;71311:16;;;:9;:16;;;;;;;;:25;;;;;;;;;;;;;71212:132;76787:1366;;;;;;:::i;:::-;;:::i;57318:28::-;;;;;-1:-1:-1;;;;;57318:28:0;;;66453:212;;;;;;:::i;:::-;;:::i;68209:328::-;;;:::i;58644:18::-;;;;;;60789:125;;;:::i;94655:815::-;;;:::i;59139:47::-;;;;;-1:-1:-1;;;;;59139:47:0;;;58669:18;;;;;;61195:167;61303:13;;61340:14;;61195:167;;60186:500;;;:::i;:::-;;;;9506:25:1;;;9562:2;9547:18;;9540:34;;;;9590:18;;;9583:34;;;;9648:2;9633:18;;9626:34;;;;9691:3;9676:19;;9669:35;9735:3;9720:19;;9713:35;9779:3;9764:19;;9757:35;9493:3;9478:19;60186:500:0;9191:607:1;57180:43:0;;;;;;65428:64;;;:::i;92391:2083::-;92732:17;;;;92731:18;92723:46;;;;-1:-1:-1;;;92723:46:0;;10005:2:1;92723:46:0;;;9987:21:1;10044:2;10024:18;;;10017:30;-1:-1:-1;;;10063:18:1;;;10056:45;10118:18;;92723:46:0;;;;;;;;;92866:4;92846:24;;-1:-1:-1;;92846:24:0;;;;;-1:-1:-1;;;;;92963:37:0;;;;;;;92955:76;;;;-1:-1:-1;;;92955:76:0;;10349:2:1;92955:76:0;;;10331:21:1;10388:2;10368:18;;;10361:30;10427:28;10407:18;;;10400:56;10473:18;;92955:76:0;10147:350:1;92955:76:0;93114:12;:39;;-1:-1:-1;;;;;93114:39:0;;;-1:-1:-1;;;;;;93114:39:0;;;;;;;93164:13;:41;;;;;;;;;;;;;;;93286:5;;;;;:20;;;93300:6;93295:1;:11;;93286:20;93278:29;;;;;;93318:3;:7;;;93409:6;93404:11;;;93396:20;;;;;;93427:3;:7;;;93500:13;:25;;;93589:13;:25;;;-1:-1:-1;93707:25:0;;-1:-1:-1;93743:15:0;;-1:-1:-1;;;;;93743:15:0;;;-1:-1:-1;;;;;;93743:15:0;;;;;;;;;;-1:-1:-1;;93707:25:0;;;;;93812:22;-1:-1:-1;;;;;;93812:22:0;;;;;;93849:27;;;;;;;;;;;-1:-1:-1;;;93849:27:0;;;;;;;;93887:28;;;;;;;;;;;-1:-1:-1;;;93887:28:0;;;;;93849:27;94065:35;94094:4;94065:20;:35::i;:::-;94031:70;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;94017:4;:85;;;;;;:::i;:::-;-1:-1:-1;94153:14:0;;;;;;;;;;;;-1:-1:-1;;;94153:14:0;;;;:6;;:14;;:6;:14;:::i;:::-;;94278:16;-1:-1:-1;;;;;94263:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94252:8;:54;;-1:-1:-1;;94252:54:0;;;;;;;;;;;;94357:22;:20;:22::i;:::-;;92667:1807;;92391:2083;;;;;;;;;:::o;57704:18::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;70504:150::-;70570:4;70587:37;70596:10;70608:7;70617:6;70587:8;:37::i;:::-;-1:-1:-1;70642:4:0;70504:150;;;;;:::o;95660:460::-;95811:42;;;;;;;;;;;-1:-1:-1;;;95811:42:0;;;;95885:12;;95895:1;95885:12;;;;;;;;;95726:13;;-1:-1:-1;;;;;95776:23:0;;;95811:42;-1:-1:-1;;95885:12:0;;;;;;;;;;-1:-1:-1;95885:12:0;95866:31;;95913:9;95908:176;95932:1;95928;:5;95908:176;;;95968:8;96000:1;95983:5;95989:6;:1;95993:2;95989:6;:::i;:::-;95983:13;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;95983:18:0;;;;95977:25;;95968:35;;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;95968:35:0;95955:3;95959:5;:1;95963;95959:5;:::i;:::-;95955:10;;;;;;;;:::i;:::-;;;;:48;-1:-1:-1;;;;;95955:48:0;;;;;;;;-1:-1:-1;96035:8:0;96050:5;96056:6;:1;96060:2;96056:6;:::i;:::-;96050:13;;;;;;;:::i;:::-;96035:37;;96050:13;;;96066:4;96044:27;;96035:37;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;96035:37:0;96018:3;96026:5;:1;96030;96026:5;:::i;:::-;96022:9;;:1;:9;:::i;:::-;96018:14;;;;;;;;:::i;:::-;;;;:54;-1:-1:-1;;;;;96018:54:0;;;;;;;;-1:-1:-1;95935:3:0;;;;:::i;:::-;;;;95908:176;;;-1:-1:-1;96108:3:0;95660:460;-1:-1:-1;;;;95660:460:0:o;69738:516::-;-1:-1:-1;;;;;69887:14:0;;69852:4;69887:14;;;:8;:14;;;;;;69877:24;;;69869:55;;;;-1:-1:-1;;;69869:55:0;;15092:2:1;69869:55:0;;;15074:21:1;15131:2;15111:18;;;15104:30;-1:-1:-1;;;15150:18:1;;;15143:48;15208:18;;69869:55:0;14890:342:1;69869:55:0;-1:-1:-1;;;;;69953:15:0;;;;;;:9;:15;;;;;;;;69969:10;69953:27;;;;;;;;69943:37;;;69935:70;;;;-1:-1:-1;;;69935:70:0;;15439:2:1;69935:70:0;;;15421:21:1;15478:2;15458:18;;;15451:30;-1:-1:-1;;;15497:18:1;;;15490:50;15557:18;;69935:70:0;15237:344:1;69935:70:0;-1:-1:-1;;;;;70035:14:0;;;;;;:8;:14;;;;;;:23;;70052:6;;70035:23;:::i;:::-;-1:-1:-1;;;;;70018:14:0;;;;;;;:8;:14;;;;;;:40;;;;70084:12;;;;;;;:21;;70099:6;;70084:21;:::i;:::-;-1:-1:-1;;;;;70069:12:0;;;;;;;:8;:12;;;;;;;;:36;;;;70146:15;;;;;:9;:15;;;;;70162:10;70146:27;;;;;;;:36;;70176:6;;70146:36;:::i;:::-;-1:-1:-1;;;;;70116:15:0;;;;;;;:9;:15;;;;;;;;70132:10;70116:27;;;;;;;;:66;;;;70198:26;2579:25:1;;;70198:26:0;;;;70116:15;;-1:-1:-1;;;;;;;;;;;70198:26:0;2552:18:1;70198:26:0;;;;;;;-1:-1:-1;70242:4:0;69738:516;;;;;:::o;85298:2876::-;85401:14;85430:17;85462:18;55093:21;:19;:21::i;:::-;85658:13:::1;::::0;85618:12:::1;::::0;:37:::1;::::0;-1:-1:-1;;;85618:37:0;;85649:4:::1;85618:37;::::0;::::1;3718:51:1::0;85596:19:0::1;::::0;85658:13;-1:-1:-1;;;;;85618:12:0::1;::::0;:22:::1;::::0;3691:18:1;;85618:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;;:::i;:::-;85746:14;::::0;85705:13:::1;::::0;;:38:::1;::::0;-1:-1:-1;;;85705:38:0;;85737:4:::1;85705:38:::0;;::::1;3718:51:1::0;;;;85596:75:0;;-1:-1:-1;85682:20:0::1;::::0;-1:-1:-1;;;;;85705:13:0::1;::::0;:23:::1;::::0;3691:18:1;;85705:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;;:::i;:::-;85845:14;::::0;85682:78;;-1:-1:-1;;;;;;85845:14:0;;::::1;::::0;-1:-1:-1;;;85893:15:0;::::1;;86005:25;85845:14:::0;86005:11;:25:::1;:::i;:::-;85993:37:::0;-1:-1:-1;86054:27:0::1;86069:12:::0;86054;:27:::1;:::i;:::-;86041:40;;86190:1;86178:9;:13;86170:39;;;::::0;-1:-1:-1;;;86170:39:0;;16110:2:1;86170:39:0::1;::::0;::::1;16092:21:1::0;16149:2;16129:18;;;16122:30;-1:-1:-1;;;16168:18:1;;;16161:43;16221:18;;86170:39:0::1;15908:337:1::0;86170:39:0::1;86406:11;;86421:1;86406:16:::0;86402:1551:::1;;86501:1;86486:12;:16;86478:46;;;::::0;-1:-1:-1;;;86478:46:0;;16452:2:1;86478:46:0::1;::::0;::::1;16434:21:1::0;16491:2;16471:18;;;16464:30;-1:-1:-1;;;16510:18:1;;;16503:47;16567:18;;86478:46:0::1;16250:341:1::0;86478:46:0::1;86613:38;86634:11;86647:3;;86613:20;:38::i;:::-;86598:12;:53;:143;;86730:11;86598:143;;;86671:39;86692:12;86706:3;;86671:20;:39::i;:::-;86799:13;:31:::0;;-1:-1:-1;;;;;;86799:31:0::1;-1:-1:-1::0;;;;;86799:31:0;::::1;;::::0;;86899:3:::1;::::0;86799:31;;-1:-1:-1;86870:33:0::1;::::0;86799:31;;86870:20:::1;:33::i;:::-;86845:14;:59:::0;;-1:-1:-1;;;;;;;;86845:59:0::1;-1:-1:-1::0;;;;;;;;86845:59:0;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;86927:14;::::1;;86919:51;;;::::0;-1:-1:-1;;;86919:51:0;;16798:2:1;86919:51:0::1;::::0;::::1;16780:21:1::0;16837:2;16817:18;;;16810:30;-1:-1:-1;;;16856:18:1;;;16849:50;16916:18;;86919:51:0::1;16596:344:1::0;86919:51:0::1;87065:4;87056:6;:13;87048:48;;;::::0;-1:-1:-1;;;87048:48:0;;17147:2:1;87048:48:0::1;::::0;::::1;17129:21:1::0;17186:2;17166:18;;;17159:30;-1:-1:-1;;;17205:18:1;;;17198:52;17267:18;;87048:48:0::1;16945:346:1::0;87048:48:0::1;87111:23;87125:1;87129:4;87111:5;:23::i;:::-;87149:14;87159:4;87149:14:::0;::::1;:::i;:::-;;;86402:1551;;;87199:1;87185:11;:15;:35;;;;;87219:1;87204:12;:16;87185:35;87181:772;;;87273:22;87298:44;87319:9;87330:11;87298:20;:44::i;:::-;87273:69;;87357:23;87383:46;87404:10;87416:12;87383:20;:46::i;:::-;87357:72;;87444:17;87482:14;87464:15;:32;:67;;87517:14;87464:67;;;87499:15;87464:67;87444:87;;87605:44;87626:11;;87639:9;87605:20;:44::i;:::-;87788:13;::::0;87596:53;;-1:-1:-1;87759:55:0::1;::::0;-1:-1:-1;;;;;87788:13:0::1;87804:9:::0;87759:20:::1;:55::i;:::-;87741:13;::::0;87733:82:::1;::::0;;-1:-1:-1;;;;;87741:13:0::1;87733:82;:::i;:::-;87709:13;:107:::0;;-1:-1:-1;;;;;;87709:107:0::1;-1:-1:-1::0;;;;;87709:107:0;;::::1;;::::0;;;;87883:56:::1;::::0;-1:-1:-1;;;87912:14:0;;::::1;;87929:9:::0;87883:20:::1;:56::i;:::-;87864:14;::::0;87856:84:::1;::::0;;-1:-1:-1;;;87864:14:0;::::1;-1:-1:-1::0;;;;;87864:14:0::1;87856:84;:::i;:::-;87831:14;;:110;;;;;-1:-1:-1::0;;;;;87831:110:0::1;;;;;-1:-1:-1::0;;;;;87831:110:0::1;;;;;;87222:731;;;87181:772;88049:17;88055:2;88059:6;88049:5;:17::i;:::-;88077:38;88089:11;88102:12;88077:11;:38::i;:::-;-1:-1:-1::0;;;;;88153:12:0;::::1;;::::0;;;:8:::1;:12;::::0;;;;;;;;;88131:35;;17498:51:1;;;17565:18;;;17558:34;;;17608:18;;;17601:34;88131:35:0;::::1;::::0;;;;17486:2:1;88131:35:0;;::::1;85497:2677;;;;55137:20:::0;54531:1;55657:7;:22;55474:213;55137:20;85298:2876;;;;;:::o;63399:174::-;63551:13;;63525:14;;63477:12;;:37;;-1:-1:-1;;;63477:37:0;;63508:4;63477:37;;;3718:51:1;63444:13:0;;63551;-1:-1:-1;;;;;63525:14:0;;-1:-1:-1;;;;;63477:12:0;;:22;;3691:18:1;;63477:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:63;;;;:::i;:::-;:88;;;;:::i;:::-;63470:95;;63399:174;:::o;83614:764::-;83740:25;83780:13;83808:27;83850:22;83900:32;83935:13;:11;:13::i;:::-;83900:48;;83992;84018:5;84025:14;83992:25;:48::i;:::-;84073:13;;84117;;83959:81;;-1:-1:-1;83959:81:0;;-1:-1:-1;84073:13:0;84149:50;83959:81;84117:13;84149:20;:50::i;:::-;84141:58;;84329:5;84263:50;84284:17;84303:9;84263:20;:50::i;:::-;84230:83;;:17;:83;:::i;:::-;:104;;;;:::i;:::-;84210:124;;84362:5;:8;;;84345:25;;83889:489;;;83614:764;;;;;;;:::o;63834:178::-;63989:14;;63962:15;;63913:13;;;:38;;-1:-1:-1;;;63913:38:0;;63945:4;63913:38;;;3718:51:1;;;;63880:13:0;;63989:14;-1:-1:-1;;;63962:15:0;;-1:-1:-1;;;;;63962:15:0;;-1:-1:-1;;;;;63913:13:0;;;;:23;;3691:18:1;;63913:38:0;3572:203:1;66745:287:0;61871:7;;-1:-1:-1;;;;;61871:7:0;61857:10;:21;61849:53;;;;-1:-1:-1;;;61849:53:0;;17848:2:1;61849:53:0;;;17830:21:1;17887:2;17867:18;;;17860:30;-1:-1:-1;;;17906:18:1;;;17899:49;17965:18;;61849:53:0;17646:343:1;61849:53:0;66883:14:::1;66904:3;;66900:1;:7;:27;;66926:1;66920:3;;:7;;;;:::i;:::-;66900:27;;;66914:3;::::0;66910:7:::1;::::0;:1;:7:::1;:::i;:::-;66883:44;;66970:13;;66962:3;;66947:6;66956:3;66947:12;;;;:::i;:::-;:18;;;;:::i;:::-;66946:37;;66938:68;;;::::0;-1:-1:-1;;;66938:68:0;;18550:2:1;66938:68:0::1;::::0;::::1;18532:21:1::0;18589:2;18569:18;;;18562:30;-1:-1:-1;;;18608:18:1;;;18601:48;18666:18;;66938:68:0::1;18348:342:1::0;66938:68:0::1;-1:-1:-1::0;67017:3:0::1;:7:::0;66745:287::o;65574:538::-;65621:8;;:47;-1:-1:-1;;;65621:8:0;;;;65640:27;65621:47;:79;;;;-1:-1:-1;65687:13:0;;65672:14;;-1:-1:-1;;;;;65687:13:0;;;65672:14;;:28;65621:79;65617:238;;;65784:14;;-1:-1:-1;;;65828:15:0;;;-1:-1:-1;;;;;65828:15:0;;;65811:32;;;65784:14;;65811:32;65715:8;65811:32;65617:238;65869:8;;:47;-1:-1:-1;;;65869:8:0;;;;65888:27;65869:47;:81;;;;-1:-1:-1;65936:14:0;;65920:15;;-1:-1:-1;;;;;;;;65936:14:0;;;;;;65920:15;;;;;:30;65869:81;65865:240;;;66034:14;;-1:-1:-1;;;66078:15:0;;;-1:-1:-1;;;;;66078:15:0;;;66061:32;;;66034:14;;66061:32;65965:8;66061:32;65865:240;65574:538::o;82358:764::-;82482:26;82523:13;82551:27;82593:21;82642:32;82677:13;:11;:13::i;:::-;82642:48;;82735:46;82760:5;82767:13;82735:24;:46::i;:::-;82814:13;;82858;;82701:80;;-1:-1:-1;82701:80:0;;-1:-1:-1;82814:13:0;82890:51;82701:80;82858:13;82890:20;:51::i;:::-;82882:59;;83074:5;83007:51;83028:18;83048:9;83007:20;:51::i;:::-;82973:85;;:18;:85;:::i;:::-;:106;;;;:::i;:::-;82952:127;;83106:5;:8;;;83090:24;;82631:491;;;82358:764;;;;;;;:::o;57563:20::-;;;;;;;:::i;59422:407::-;59466:32;;:::i;:::-;59521:3;;59511:13;;59545:3;;59535:7;;;:13;59569:14;;-1:-1:-1;;;;;59569:14:0;;;59559:7;;;:24;-1:-1:-1;;;59604:15:0;;;;;;59594:7;;;:25;59641:13;;;;;59630:8;;;:24;59716:14;;;;59705:8;;;:25;-1:-1:-1;;;59769:8:0;;;;59751:27;;;;;;;;:::i;:::-;59741:5;:7;;:37;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;59789:32:0;59815:5;59789:25;:32::i;:::-;59422:407;:::o;68764:332::-;68870:10;68826:4;68861:20;;;:8;:20;;;;;;68851:30;;;68843:61;;;;-1:-1:-1;;;68843:61:0;;15092:2:1;68843:61:0;;;15074:21:1;15131:2;15111:18;;;15104:30;-1:-1:-1;;;15150:18:1;;;15143:48;15208:18;;68843:61:0;14890:342:1;68843:61:0;68949:10;68940:20;;;;:8;:20;;;;;;:31;;68964:6;;68940:31;:::i;:::-;68926:10;68917:20;;;;:8;:20;;;;;;:54;;;;-1:-1:-1;;;;;68997:12:0;;;;;;:21;;69012:6;;68997:21;:::i;:::-;-1:-1:-1;;;;;68982:12:0;;;;;;:8;:12;;;;;;;:36;;;;69034:32;;69043:10;;-1:-1:-1;;;;;;;;;;;69034:32:0;;;69059:6;2579:25:1;;2567:2;2552:18;;2433:177;69034:32:0;;;;;;;;-1:-1:-1;69084:4:0;68764:332;;;;:::o;88831:2488::-;89062:18;89082:19;55093:21;:19;:21::i;:::-;89200:15:::1;89188:8;:27;;89180:52;;;::::0;-1:-1:-1;;;89180:52:0;;18897:2:1;89180:52:0::1;::::0;::::1;18879:21:1::0;18936:2;18916:18;;;18909:30;-1:-1:-1;;;18955:18:1;;;18948:42;19007:18;;89180:52:0::1;18695:336:1::0;89180:52:0::1;89361:10;89352:20;::::0;;;:8:::1;:20;::::0;;;;;89337:35;::::1;;89329:62;;;::::0;-1:-1:-1;;;89329:62:0;;19238:2:1;89329:62:0::1;::::0;::::1;19220:21:1::0;19277:2;19257:18;;;19250:30;-1:-1:-1;;;19296:18:1;;;19289:44;19350:18;;89329:62:0::1;19036:338:1::0;89329:62:0::1;89554:13;::::0;89514:12:::1;::::0;:37:::1;::::0;-1:-1:-1;;;89514:37:0;;89545:4:::1;89514:37;::::0;::::1;3718:51:1::0;89492:19:0::1;::::0;89554:13;-1:-1:-1;;;;;89514:12:0::1;::::0;:22:::1;::::0;3691:18:1;;89514:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;;:::i;:::-;89642:14;::::0;89601:13:::1;::::0;;:38:::1;::::0;-1:-1:-1;;;89601:38:0;;89633:4:::1;89601:38:::0;;::::1;3718:51:1::0;;;;89492:75:0;;-1:-1:-1;89578:20:0::1;::::0;-1:-1:-1;;;;;89601:13:0::1;::::0;:23:::1;::::0;3691:18:1;;89601:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;;:::i;:::-;89725:11;::::0;89578:78;;-1:-1:-1;89725:11:0;89891:25:::1;89905:11:::0;89891;:25:::1;:::i;:::-;:39;;;;:::i;:::-;89878:52:::0;-1:-1:-1;89984:11:0;89955:26:::1;89970:11:::0;89955:12;:26:::1;:::i;:::-;:40;;;;:::i;:::-;90134:13;::::0;89941:54;;-1:-1:-1;90104:75:0::1;::::0;90126:38:::1;::::0;90152:11;;-1:-1:-1;;;;;90134:13:0::1;90126:38;:::i;:::-;90167:11;90104:20;:75::i;:::-;90087:13;::::0;90079:100:::1;::::0;;-1:-1:-1;;;;;90087:13:0::1;90079:100;:::i;:::-;90055:13;:125:::0;;-1:-1:-1;;;;;;90055:125:0::1;-1:-1:-1::0;;;;;90055:125:0;;::::1;;::::0;;;;90242:76:::1;::::0;90264:39:::1;::::0;90291:11;;-1:-1:-1;;;90272:14:0;;::::1;;90264:39;:::i;90242:76::-;90224:14;::::0;90216:102:::1;::::0;;-1:-1:-1;;;90224:14:0;::::1;-1:-1:-1::0;;;;;90224:14:0::1;90216:102;:::i;:::-;90191:14;;:128;;;;;-1:-1:-1::0;;;;;90191:128:0::1;;;;;-1:-1:-1::0;;;;;90191:128:0::1;;;;;;90485:13;90471:10;:27;;:60;;;;;90517:14;90502:11;:29;;90471:60;90449:129;;;::::0;-1:-1:-1;;;90449:129:0;;19581:2:1;90449:129:0::1;::::0;::::1;19563:21:1::0;19620:2;19600:18;;;19593:30;-1:-1:-1;;;19639:18:1;;;19632:49;19698:18;;90449:129:0::1;19379:343:1::0;90449:129:0::1;90747:30;90753:10;90765:11;90747:5;:30::i;:::-;90788:32;90805:2;90809:10;90788:16;:32::i;:::-;90831:34;90849:2;90853:11;90831:17;:34::i;:::-;90876:7;:5;:7::i;:::-;90973:15:::0;;90969:264:::1;;91045:2;-1:-1:-1::0;;;;;91033:32:0::1;;91084:10;91113:11;91143:10;91172:11;91202:4;;91033:188;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;90969:264;91261:10;91290:20;::::0;;;:8:::1;:20;::::0;;;;;;;;;91250:61;;20829:34:1;;;-1:-1:-1;;;;;20899:15:1;;20879:18;;;20872:43;;;;20931:18;;;20924:34;;;20989:2;20974:18;;20967:34;91250:61:0;::::1;::::0;;;;20778:3:1;91250:61:0;;::::1;89103:2216;;;55137:20:::0;54531:1;55657:7;:22;55474:213;55137:20;88831:2488;;;;;;;;;;:::o;67205:174::-;61708:12;;;;;-1:-1:-1;;;;;61708:12:0;61694:10;:26;61686:52;;;;-1:-1:-1;;;61686:52:0;;21214:2:1;61686:52:0;;;21196:21:1;21253:2;21233:18;;;21226:30;-1:-1:-1;;;21272:18:1;;;21265:43;21325:18;;61686:52:0;21012:337:1;61686:52:0;67305:6:::1;67292:9;:19;;67284:51;;;::::0;-1:-1:-1;;;67284:51:0;;21556:2:1;67284:51:0::1;::::0;::::1;21538:21:1::0;21595:2;21575:18;;;21568:30;-1:-1:-1;;;21614:18:1;;;21607:49;21673:18;;67284:51:0::1;21354:343:1::0;67284:51:0::1;67346:13;:25:::0;67205:174::o;75224:1337::-;75285:26;55093:21;:19;:21::i;:::-;75386:13:::1;::::0;75346:12:::1;::::0;:37:::1;::::0;-1:-1:-1;;;75346:37:0;;75377:4:::1;75346:37;::::0;::::1;3718:51:1::0;75324:19:0::1;::::0;75386:13;-1:-1:-1;;;;;75346:12:0::1;::::0;:22:::1;::::0;3691:18:1;;75346:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;;:::i;:::-;75452:14;::::0;75324:75;;-1:-1:-1;75410:17:0::1;::::0;75430:37:::1;::::0;-1:-1:-1;;;;;75452:14:0::1;75324:75:::0;75430:37:::1;:::i;:::-;75410:57;;75478:13;75502:21:::0;75534:27:::1;75698:35;75712:9;75723;75698:13;:35::i;:::-;75642:91:::0;;-1:-1:-1;75642:91:0;;-1:-1:-1;75642:91:0;;-1:-1:-1;75642:91:0;-1:-1:-1;75790:41:0::1;75808:2:::0;75642:91;75790:17:::1;:41::i;:::-;75917:5;75900:14;;:22;;;;:::i;:::-;75883:14;:39:::0;75994:9;75987:17:::1;::::0;::::1;;;;;;:::i;:::-;75975:8;::::0;-1:-1:-1;;;75975:8:0;::::1;:29;:8:::0;;::::1;:29:::0;::::1;;75971:255;;-1:-1:-1::0;;;;;76033:34:0;::::1;;76025:55;;;;-1:-1:-1::0;;;76025:55:0::1;;;;;;;:::i;:::-;76095:13;:38:::0;;-1:-1:-1;;;;;;76095:38:0::1;-1:-1:-1::0;;;;;76095:38:0;::::1;;::::0;;76166:9;76159:17:::1;::::0;::::1;;;;;;:::i;:::-;76148:8;;:28;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;76204:9:0::1;76196:18;;;;;;:::i;:::-;;;;;;;;75971:255;76329:14;::::0;76288:13:::1;::::0;;:38:::1;::::0;-1:-1:-1;;;76288:38:0;;76320:4:::1;76288:38:::0;;::::1;3718:51:1::0;;;;76263:81:0::1;::::0;76275:11;;76329:14;;-1:-1:-1;;;;;76288:13:0::1;::::0;:23:::1;::::0;3691:18:1;;76288:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;;:::i;:::-;76263:11;:81::i;:::-;76393:12;::::0;76429:13:::1;::::0;76362:191:::1;::::0;-1:-1:-1;;;;;;;;;;;76362:191:0;::::1;::::0;-1:-1:-1;;;;;76393:12:0;;::::1;::::0;76429:13;::::1;::::0;76458:9;;76482:18;;76515:10:::1;::::0;76540:2;;76362:191:::1;:::i;:::-;;;;;;;;75313:1248;;;;;55137:20:::0;54531:1;55657:7;:22;55474:213;55137:20;75224:1337;;;:::o;78513:3306::-;55093:21;:19;:21::i;:::-;78687:37:::1;78704:7;78713:10;78687:16;:37::i;:::-;78735:39;78753:7;78762:11;78735:17;:39::i;:::-;78791:15:::0;;78787:114:::1;;78821:80;::::0;-1:-1:-1;;;78821:80:0;;-1:-1:-1;;;;;78821:37:0;::::1;::::0;::::1;::::0;:80:::1;::::0;78859:10:::1;::::0;78871;;78883:11;;78896:4;;;;78821:80:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;78787:114;78976:13;::::0;78936:12:::1;::::0;:37:::1;::::0;-1:-1:-1;;;78936:37:0;;78967:4:::1;78936:37;::::0;::::1;3718:51:1::0;78914:19:0::1;::::0;78976:13;-1:-1:-1;;;;;78936:12:0::1;::::0;:22:::1;::::0;3691:18:1;;78936:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;;:::i;:::-;79064:14;::::0;79023:13:::1;::::0;;:38:::1;::::0;-1:-1:-1;;;79023:38:0;;79055:4:::1;79023:38:::0;;::::1;3718:51:1::0;;;;78914:75:0;;-1:-1:-1;79000:20:0::1;::::0;-1:-1:-1;;;;;79023:13:0::1;::::0;:23:::1;::::0;3691:18:1;;79023:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;;:::i;:::-;79162:14;::::0;79000:78;;-1:-1:-1;;;;;;79162:14:0::1;79147:29:::0;::::1;;::::0;:64:::1;;-1:-1:-1::0;79196:15:0::1;::::0;-1:-1:-1;;;79196:15:0;::::1;-1:-1:-1::0;;;;;79196:15:0::1;79180:31:::0;::::1;;79147:64;79125:131;;;;-1:-1:-1::0;;;79125:131:0::1;;;;;;;:::i;:::-;79353:14;::::0;-1:-1:-1;;;;;79353:14:0::1;79339:28:::0;::::1;79335:1159;;;79428:15;::::0;79384:18:::1;::::0;79405:39:::1;::::0;-1:-1:-1;;;79428:15:0;::::1;-1:-1:-1::0;;;;;79428:15:0::1;79405:12:::0;:39:::1;:::i;:::-;79384:60;;79478:25;79522:13:::0;79554:27:::1;79600:22:::0;79640:37:::1;79655:9;79666:10;79640:14;:37::i;:::-;79766:14;::::0;79459:218;;-1:-1:-1;79459:218:0;;-1:-1:-1;79459:218:0;-1:-1:-1;79459:218:0;-1:-1:-1;79459:218:0;;79758:37:::1;::::0;79784:11;;-1:-1:-1;;;;;79766:14:0::1;79758:37;:::i;:::-;79757:60;;79731:139;;;;-1:-1:-1::0;;;79731:139:0::1;;;;;;;:::i;:::-;79931:5;79915:13;;:21;;;;:::i;:::-;79899:13;:37:::0;79988:9;79981:17:::1;::::0;::::1;;;;;;:::i;:::-;79969:8;::::0;-1:-1:-1;;;79969:8:0;::::1;:29;:8:::0;;::::1;:29:::0;::::1;;79965:274;;-1:-1:-1::0;;;;;80027:35:0;::::1;;80019:56;;;;-1:-1:-1::0;;;80019:56:0::1;;;;;;;:::i;:::-;80094:14;:40:::0;;-1:-1:-1;;;;;;;;80094:40:0::1;-1:-1:-1::0;;;;;;;;80094:40:0;::::1;;;::::0;;80171:9;80164:17:::1;::::0;::::1;;;;;;:::i;:::-;80153:8;;:28;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;80213:9:0::1;80205:18;;;;;;:::i;:::-;;;;;;;;79965:274;-1:-1:-1::0;;;;;;;;;;;80293:13:0::1;;;;;;;;;-1:-1:-1::0;;;;;80293:13:0::1;80334:12;;;;;;;;;-1:-1:-1::0;;;;;80334:12:0::1;80366:10;80395:17;80431:10;80460:7;80258:224;;;;;;;;;;;:::i;:::-;;;;;;;;79369:1125;;;;;79335:1159;80590:15;::::0;-1:-1:-1;;;80590:15:0;::::1;-1:-1:-1::0;;;;;80590:15:0::1;80575:30:::0;::::1;80571:1144;;;80664:14;::::0;80622:17:::1;::::0;80642:37:::1;::::0;-1:-1:-1;;;;;80664:14:0::1;80642:11:::0;:37:::1;:::i;:::-;80622:57;;80713:26;80758:13:::0;80790:27:::1;80836:21:::0;80875:35:::1;80889:9;80900;80875:13;:35::i;:::-;80997:15;::::0;80694:216;;-1:-1:-1;80694:216:0;;-1:-1:-1;80694:216:0;-1:-1:-1;80694:216:0;-1:-1:-1;80694:216:0;;80989:39:::1;::::0;81016:12;;-1:-1:-1;;;80997:15:0;::::1;-1:-1:-1::0;;;;;80997:15:0::1;80989:39;:::i;:::-;80988:63;;80962:142;;;;-1:-1:-1::0;;;80962:142:0::1;;;;;;;:::i;:::-;81155:5;81138:14;;:22;;;;:::i;:::-;81121:14;:39:::0;81212:9;81205:17:::1;::::0;::::1;;;;;;:::i;:::-;81193:8;::::0;-1:-1:-1;;;81193:8:0;::::1;:29;:8:::0;;::::1;:29:::0;::::1;;81189:271;;-1:-1:-1::0;;;;;81251:34:0;::::1;;81243:55;;;;-1:-1:-1::0;;;81243:55:0::1;;;;;;;:::i;:::-;81317:13;:38:::0;;-1:-1:-1;;;;;;81317:38:0::1;-1:-1:-1::0;;;;;81317:38:0;::::1;;::::0;;81392:9;81385:17:::1;::::0;::::1;;;;;;:::i;:::-;81374:8;;:28;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;81434:9:0::1;81426:18;;;;;;:::i;:::-;;;;;;;;81189:271;-1:-1:-1::0;;;;;;;;;;;81514:12:0::1;;;;;;;;;-1:-1:-1::0;;;;;81514:12:0::1;81554:13;;;;;;;;;-1:-1:-1::0;;;;;81554:13:0::1;81587:9;81615:18;81652:10;81681:7;81479:224;;;;;;;;;;;:::i;:::-;;;;;;;;80607:1108;;;;;80571:1144;81727:7;:5;:7::i;:::-;81752:59;::::0;;81766:10:::1;20829:34:1::0;;-1:-1:-1;;;;;20899:15:1;;20894:2;20879:18;;20872:43;20931:18;;;20924:34;;;20989:2;20974:18;;20967:34;;;81752:59:0::1;::::0;20778:3:1;20763:19;81752:59:0::1;;;;;;;78676:3143;;55137:20:::0;54531:1;55657:7;:22;55474:213;55137:20;78513:3306;;;;;:::o;71985:1079::-;72207:15;72195:8;:27;;72187:60;;;;-1:-1:-1;;;72187:60:0;;23897:2:1;72187:60:0;;;23879:21:1;23936:2;23916:18;;;23909:30;-1:-1:-1;;;23955:18:1;;;23948:50;24015:18;;72187:60:0;23695:344:1;72187:60:0;72388:16;;-1:-1:-1;;;;;72660:13:0;;72258:14;72660:13;;;:6;:13;;;;;:15;;72258:14;;72388:16;58299:66;;72550:5;;72586:7;;72624:5;;72660:15;72258:14;72660:15;;;:::i;:::-;;;;-1:-1:-1;72463:278:0;;;;;;24331:25:1;;;;-1:-1:-1;;;;;24430:15:1;;;24410:18;;;24403:43;24482:15;;;;24462:18;;;24455:43;24514:18;;;24507:34;24557:19;;;24550:35;24601:19;;;24594:35;;;24303:19;;72463:278:0;;;;;;;;;;;;72427:337;;;;;;72316:467;;;;;;;;-1:-1:-1;;;24898:27:1;;24950:1;24941:11;;24934:27;;;;24986:2;24977:12;;24970:28;25023:2;25014:12;;24640:392;72316:467:0;;;;-1:-1:-1;;72316:467:0;;;;;;;;;72288:510;;72316:467;72288:510;;;;72811:24;72838:26;;;;;;;;;25264:25:1;;;25337:4;25325:17;;25305:18;;;25298:45;;;;25359:18;;;25352:34;;;25402:18;;;25395:34;;;72288:510:0;;-1:-1:-1;72811:24:0;72838:26;;25236:19:1;;72838:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;72838:26:0;;-1:-1:-1;;72838:26:0;;;-1:-1:-1;;;;;;;72897:30:0;;;;;;:59;;;72951:5;-1:-1:-1;;;;;72931:25:0;:16;-1:-1:-1;;;;;72931:25:0;;72897:59;72875:139;;;;-1:-1:-1;;;72875:139:0;;25642:2:1;72875:139:0;;;25624:21:1;25681:2;25661:18;;;25654:30;25720:32;25700:18;;;25693:60;25770:18;;72875:139:0;25440:354:1;72875:139:0;73025:31;73034:5;73041:7;73050:5;73025:8;:31::i;:::-;72176:888;;71985:1079;;;;;;;:::o;76787:1366::-;76849:25;55093:21;:19;:21::i;:::-;76951:14:::1;::::0;76910:13:::1;::::0;;:38:::1;::::0;-1:-1:-1;;;76910:38:0;;76942:4:::1;76910:38:::0;;::::1;3718:51:1::0;;;;76887:20:0::1;::::0;76951:14;-1:-1:-1;;;;;76910:13:0;;::::1;::::0;:23:::1;::::0;3691:18:1;;76910:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;;:::i;:::-;77020:15;::::0;76887:78;;-1:-1:-1;76976:18:0::1;::::0;76997:39:::1;::::0;-1:-1:-1;;;77020:15:0;::::1;-1:-1:-1::0;;;;;77020:15:0::1;76887:78:::0;76997:39:::1;:::i;:::-;76976:60;;77047:13;77071:22:::0;77104:27:::1;77267:74;77296:9;77320:10;77267:14;:74::i;:::-;77211:130:::0;;-1:-1:-1;77211:130:0;;-1:-1:-1;77211:130:0;;-1:-1:-1;77211:130:0;-1:-1:-1;77397:39:0::1;77414:2:::0;77211:130;77397:16:::1;:39::i;:::-;77519:5;77503:13;;:21;;;;:::i;:::-;77487:13;:37:::0;77586:9;77579:17:::1;::::0;::::1;;;;;;:::i;:::-;77567:8;::::0;-1:-1:-1;;;77567:8:0;::::1;:29;:8:::0;;::::1;:29:::0;::::1;;77563:254;;-1:-1:-1::0;;;;;77621:35:0;::::1;;77613:56;;;;-1:-1:-1::0;;;77613:56:0::1;;;;;;;:::i;:::-;77684:14;:40:::0;;-1:-1:-1;;;;;;;;77684:40:0::1;-1:-1:-1::0;;;;;;;;77684:40:0;::::1;;;::::0;;77757:9;77750:17:::1;::::0;::::1;;;;;;:::i;:::-;77739:8;;:28;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;77795:9:0::1;77787:18;;;;;;:::i;:::-;;;;;;;;77563:254;77907:13;::::0;77867:12:::1;::::0;:37:::1;::::0;-1:-1:-1;;;77867:37:0;;77898:4:::1;77867:37;::::0;::::1;3718:51:1::0;77854:82:0::1;::::0;77907:13;-1:-1:-1;;;;;77867:12:0::1;::::0;:22:::1;::::0;3691:18:1;;77867:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;;:::i;:::-;77923:12;77854:11;:82::i;:::-;77985:13;::::0;78022:12:::1;::::0;77954:191:::1;::::0;-1:-1:-1;;;;;;;;;;;77954:191:0;::::1;::::0;-1:-1:-1;;;;;77985:13:0;;::::1;::::0;78022:12;::::1;::::0;78050:10;;78075:17;;78107:10:::1;::::0;78132:2;;77954:191:::1;:::i;66453:212::-:0;61871:7;;-1:-1:-1;;;;;61871:7:0;61857:10;:21;61849:53;;;;-1:-1:-1;;;61849:53:0;;17848:2:1;61849:53:0;;;17830:21:1;17887:2;17867:18;;;17860:30;-1:-1:-1;;;17906:18:1;;;17899:49;17965:18;;61849:53:0;17646:343:1;61849:53:0;66593:3:::1;66579:10;:17;;66571:49;;;::::0;-1:-1:-1;;;66571:49:0;;26001:2:1;66571:49:0::1;::::0;::::1;25983:21:1::0;26040:2;26020:18;;;26013:30;-1:-1:-1;;;26059:18:1;;;26052:49;26118:18;;66571:49:0::1;25799:343:1::0;66571:49:0::1;66631:13;:26:::0;66453:212::o;68209:328::-;55093:21;:19;:21::i;:::-;61708:12:::1;::::0;;;::::1;-1:-1:-1::0;;;;;61708:12:0::1;61694:10;:26;61686:52;;;::::0;-1:-1:-1;;;61686:52:0;;21214:2:1;61686:52:0::1;::::0;::::1;21196:21:1::0;21253:2;21233:18;;;21226:30;-1:-1:-1;;;21272:18:1;;;21265:43;21325:18;;61686:52:0::1;21012:337:1::0;61686:52:0::1;68308:14:::2;::::0;;68353:13:::2;::::0;68287:18:::2;68377::::0;;;-1:-1:-1;68424:12:0;68308:14;;68353:13;68406:43:::2;::::0;68424:12;;::::2;-1:-1:-1::0;;;;;68424:12:0::2;68308:14:::0;68406:17:::2;:43::i;:::-;68476:1;68460:13;:17:::0;68505:12:::2;::::0;68488:41:::2;::::0;68505:12;;::::2;-1:-1:-1::0;;;;;68505:12:0::2;68519:9:::0;68488:16:::2;:41::i;:::-;68276:261;;55137:20:::0;54531:1;55657:7;:22;55474:213;60789:125;60833:16;60869:37;60892:13;:11;:13::i;:::-;60869:22;:37::i;94655:815::-;94722:27;;;;;;;;;;;-1:-1:-1;;;94722:27:0;;;;;;;;94760:28;;;;;;;;;;;-1:-1:-1;;;94760:28:0;;;;94703:7;;;94760:28;94722:27;94952:35;94981:4;94952:20;:35::i;:::-;94918:70;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;94918:70:0;;;;;;;;;95276:22;;94918:70;95276:22;;;;95327:10;;;;;;;;-1:-1:-1;;;95327:10:0;;;;;;;95045:372;;95191:66;95045:372;;;26490:25:1;26531:18;;;26524:34;;;;95317:21:0;26574:18:1;;;26567:34;95357:13:0;26617:18:1;;;26610:34;95397:4:0;26660:19:1;;;;26653:61;;;;95045:372:0;;;;;;;;;;26462:19:1;;;;95045:372:0;;;95021:407;;;;;95002:16;:426;;;95021:407;;-1:-1:-1;;;;94655:815:0:o;60186:500::-;60280:9;60304;60328;60352;60376:10;60401;60426:9;60463:32;60498:13;:11;:13::i;:::-;60463:48;;60526:5;:7;;;60522:11;;60548:5;:7;;;60544:11;;60570:5;:7;;;60566:11;;60592:5;:7;;;60588:11;;60615:5;:8;;;60610:13;;60639:5;:8;;;60634:13;;60670:5;:7;;;60662:16;;;;;;;;:::i;:::-;60658:20;;60452:234;60186:500;;;;;;;:::o;65428:64::-;55093:21;:19;:21::i;:::-;65477:7:::1;:5;:7::i;:::-;55137:20:::0;54531:1;55657:7;:22;55474:213;70662:209;-1:-1:-1;;;;;70781:16:0;;;;;;;:9;:16;;;;;;;;:25;;;;;;;;;;;;;:34;;;70831:32;;2579:25:1;;;70831:32:0;;2552:18:1;70831:32:0;;;;;;;70662:209;;;:::o;55173:293::-;54575:1;55307:7;;:19;55299:63;;;;-1:-1:-1;;;55299:63:0;;26927:2:1;55299:63:0;;;26909:21:1;26966:2;26946:18;;;26939:30;27005:33;26985:18;;;26978:61;27056:18;;55299:63:0;26725:355:1;55299:63:0;54575:1;55440:7;:18;55173:293::o;17133:126::-;17201:7;17242:8;17228:10;17237:1;17228:6;:10;:::i;:::-;:23;;;;:::i;:::-;17221:30;17133:126;-1:-1:-1;;;17133:126:0:o;17536:::-;17604:7;17653:1;17631:19;:6;17641:8;17631:19;:::i;71352:295::-;71432:4;71424:5;:12;71416:47;;;;-1:-1:-1;;;71416:47:0;;17147:2:1;71416:47:0;;;17129:21:1;17186:2;17166:18;;;17159:30;-1:-1:-1;;;17205:18:1;;;17198:52;17267:18;;71416:47:0;16945:346:1;71416:47:0;-1:-1:-1;;;;;71491:14:0;;;;;;:8;:14;;;;;;:22;;71508:5;;71491:22;:::i;:::-;-1:-1:-1;;;;;71474:14:0;;;;;;:8;:14;;;;;:39;71538:11;;:19;;71552:5;;71538:19;:::i;:::-;71524:11;:33;71573:17;;2579:25:1;;;-1:-1:-1;;;;;71573:17:0;;;;;2567:2:1;2552:18;71573:17:0;;;;;;;71606:33;;2579:25:1;;;-1:-1:-1;;;;;71606:33:0;;;71623:1;;-1:-1:-1;;;;;;;;;;;71606:33:0;2567:2:1;2552:18;71606:33:0;;;;;;;;71352:295;;:::o;64249:341::-;-1:-1:-1;;;;;64402:32:0;;;;;:69;;-1:-1:-1;;;;;;64438:33:0;;;64402:69;64394:90;;;;-1:-1:-1;;;64394:90:0;;;;;;;:::i;:::-;64495:14;:37;;-1:-1:-1;;;;;64543:39:0;;;-1:-1:-1;;;64543:39:0;-1:-1:-1;;;;;;64543:39:0;;;64495:37;;;;64543:39;;;;;;;;;;64249:341::o;28242:1381::-;28363:25;;;28423:5;:7;;;:21;;;;;;;;:::i;:::-;;28419:1197;;28481:42;28501:5;28508:14;28481:19;:42::i;:::-;28461:62;;28545:16;28538:23;;28419:1197;;;28594:16;28583:5;:7;;;:27;;;;;;;;:::i;:::-;;28579:1037;;28647:44;28669:5;28676:14;28647:21;:44::i;28579:1037::-;28762:25;28801:5;:7;;;28790:5;:8;;;:18;;;;:::i;:::-;28762:46;;28823:28;28864:5;:8;;;28854:5;:7;;;:18;;;;:::i;:::-;28823:49;;28908:17;28891:14;:34;28887:718;;;28966:44;28988:5;28995:14;28966:21;:44::i;:::-;28946:64;;29037:16;29030:23;;29096:20;29076:17;:40;29072:129;;;29161:20;29141:40;;29072:129;28887:718;;;29244:17;29226:14;:35;29222:383;;29302:20;29282:40;;29348:10;29341:17;;29222:383;;;29465:62;29485:5;29492:34;29509:17;29492:14;:34;:::i;:::-;29465:19;:62::i;:::-;29419:128;;:20;:128;:::i;:::-;29399:148;;29573:16;29566:23;;29222:383;28747:869;;28579:1037;28242:1381;;;;;:::o;25863:2041::-;25982:26;;;26043:5;:7;;;:21;;;;;;;;:::i;:::-;;26039:1858;;26164:40;26183:5;26190:13;26164:18;:40::i;:::-;26143:61;;26226:16;26219:23;;26039:1858;;;26275:16;26264:5;:7;;;:27;;;;;;;;:::i;:::-;;26260:1637;;26308:24;26346:5;:7;;;26335:5;:8;;;:18;;;;:::i;:::-;26308:45;;26368:29;26410:5;:8;;;26400:5;:7;;;:18;;;;:::i;:::-;26368:50;;26546:16;26530:13;:32;26526:1154;;;26657:42;26678:5;26685:13;26657:20;:42::i;:::-;26636:63;;26725:16;26718:23;;26785:21;26764:18;:42;26760:402;;;27121:21;27100:42;;26760:402;26526:1154;;;27204:16;27187:13;:33;27183:497;;27316:21;27295:42;;27363:10;27356:17;;27183:497;;;27542:61;27561:5;27569:32;27585:16;27569:13;:32;:::i;:::-;27542:18;:61::i;:::-;27495:127;;:21;:127;:::i;:::-;27474:148;;27648:16;27641:23;;27183:497;26293:1398;;26260:1637;;;27805:42;27826:5;27833:13;27805:20;:42::i;:::-;27784:63;27869:16;;-1:-1:-1;25863:2041:0;-1:-1:-1;;;25863:2041:0:o;32610:598::-;32697:16;32686:5;:7;;;:27;;;;;;;;:::i;:::-;;32682:519;;32741:171;32801:5;:7;;;32837:5;:8;;;32827:5;:7;;;:18;;;;:::i;:::-;32864:7;;32890;;;;32741:41;:171::i;:::-;32730:8;;;:182;32610:598;:::o;32682:519::-;32945:16;32934:5;:7;;;:27;;;;;;;;:::i;:::-;;32930:271;;32989:200;33049:5;:7;;;33085:5;:8;;;33075:5;:7;;;:18;;;;:::i;:::-;33140:7;;33112:36;;:27;:36::i;:::-;33167:5;:7;;;32989:41;:200::i;:::-;32978:8;;;:211;32930:271;32610:598;:::o;18640:285::-;18703:7;;18742:5;18746:1;18742;:5;:::i;:::-;18723:24;-1:-1:-1;18758:17:0;18782:12;18793:1;18723:24;18782:12;:::i;:::-;18778:16;;:1;:16;:::i;:::-;18758:36;-1:-1:-1;18809:13:0;;18805:113;;18846:12;:8;18857:1;18846:12;:::i;:::-;18839:19;;;;;;18805:113;-1:-1:-1;18898:8:0;-1:-1:-1;18891:15:0;;71655:237;-1:-1:-1;;;;;71736:14:0;;;;;;:8;:14;;;;;;:22;;71753:5;;71736:22;:::i;:::-;-1:-1:-1;;;;;71719:14:0;;;;;;:8;:14;;;;;:39;71783:11;;:19;;71797:5;;71783:19;:::i;:::-;71769:11;:33;71818:17;;2579:25:1;;;-1:-1:-1;;;;;71818:17:0;;;;;2567:2:1;2552:18;71818:17:0;;;;;;;71851:33;;2579:25:1;;;71874:1:0;;-1:-1:-1;;;;;71851:33:0;;;-1:-1:-1;;;;;;;;;;;71851:33:0;2567:2:1;2552:18;71851:33:0;2433:177:1;67617:161:0;67695:10;;67691:80;;67722:12;;:37;;-1:-1:-1;;;;;67722:12:0;67748:2;67752:6;67722:25;:37::i;:::-;67617:161;;:::o;67974:163::-;68053:10;;68049:81;;68080:13;;:38;;-1:-1:-1;;;;;68080:13:0;68107:2;68111:6;68080:26;:38::i;64762:611::-;64869:13;;64821:12;;:37;;-1:-1:-1;;;64821:37:0;;64852:4;64821:37;;;3718:51:1;64799:19:0;;64869:13;-1:-1:-1;;;;;64821:12:0;;:22;;3691:18:1;;64821:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:62;;;;:::i;:::-;64966:14;;64917:13;;;:38;;-1:-1:-1;;;64917:38:0;;64949:4;64917:38;;;3718:51:1;;;;64799:84:0;;-1:-1:-1;64894:20:0;;-1:-1:-1;;;;;64917:13:0;;:23;;3691:18:1;;64917:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;;;;:::i;:::-;64894:87;-1:-1:-1;;;;;;65061:32:0;;;;;:69;;-1:-1:-1;;;;;;65097:33:0;;;65061:69;65053:90;;;;-1:-1:-1;;;65053:90:0;;;;;;;:::i;:::-;65173:14;;-1:-1:-1;;;;;65173:14:0;65158:29;;65154:99;;65204:14;:37;;-1:-1:-1;;;;;;65204:37:0;-1:-1:-1;;;;;65204:37:0;;;;;65154:99;65283:15;;-1:-1:-1;;;65283:15:0;;-1:-1:-1;;;;;65283:15:0;65267:31;;65263:103;;65315:15;:39;;-1:-1:-1;;;;;65315:39:0;;-1:-1:-1;;;65315:39:0;-1:-1:-1;;;;;;;;65315:39:0;;;;;;64788:585;;64762:611::o;33216:601::-;33283:7;33318:16;33307:5;:7;;;:27;;;;;;;;:::i;:::-;;33303:507;;33406:7;;;;33395:8;;;;33351:9;;33363:60;;33384:19;;33395:8;33384:19;:::i;:::-;:29;;;;:::i;:::-;33415:5;:7;;;33363:20;:60::i;:::-;33351:72;;33471:32;33492:5;:7;;;33501:1;33471:20;:32::i;:::-;33460:7;;;;33442:25;;16939:8;33442:25;:::i;:::-;:62;;;;:::i;:::-;33438:66;;33526:32;33547:5;:7;;;33556:1;33526:20;:32::i;33303:507::-;33646:7;;;;33635:8;;;;33591:9;;33603:60;;33624:19;;33635:8;33624:19;:::i;:::-;:29;;;;:::i;:::-;33655:5;:7;;;33603:20;:60::i;:::-;33591:72;;33711:32;33732:5;:7;;;33741:1;33711:20;:32::i;:::-;33700:7;;;;33682:25;;16939:8;33682:25;:::i;:::-;:62;;;;:::i;:::-;33678:66;;33766:32;33787:5;:7;;;33796:1;33766:20;:32::i;30257:446::-;30397:7;30472:223;30531:5;:8;;;30558:5;:8;;;30585:14;30618:36;30646:5;:7;;;30618:27;:36::i;:::-;30673:5;:7;;;30472:40;:223::i;32102:447::-;32244:7;32319:222;32378:5;:8;;;32405:5;:7;;;32431:14;32464:36;32492:5;:7;;;32464:27;:36::i;30759:443::-;30901:7;30976:218;31021:5;:8;;;31058:14;31048:5;:7;;;:24;;;;:::i;:::-;31091:7;;;;31145;;31117:36;;:27;:36::i;:::-;31172:5;:7;;;30976:26;:218::i;29679:570::-;29817:7;30048:193;30107:5;:8;;;30134:5;:8;;;30161:13;30193:5;:7;;;30219:5;:7;;;30048:40;:193::i;31682:412::-;31822:7;31898:188;31943:5;:8;;;31980:13;31970:5;:7;;;:23;;;;:::i;:::-;32012:7;;;;32038;;32064;;;;31898:26;:188::i;31210:416::-;31350:7;31426:192;31485:5;:8;;;31512:5;:7;;;31538:13;31570:5;:7;;;31596:5;:7;;;31426:40;:192::i;20445:1090::-;20602:7;20626:1;20631;20626:6;20622:81;;20661:30;20682:1;20685:5;20661:20;:30::i;:::-;20656:35;;:2;:35;:::i;:::-;20649:42;;;;20622:81;20920:2;20926:1;20920:7;20916:48;;-1:-1:-1;20951:1:0;20944:8;;20916:48;20974:12;;21018:1;21010:5;21014:1;21010;:5;:::i;:::-;:9;;;;:::i;:::-;20997:22;;21036:2;21042:1;21036:7;21032:262;;16939:8;21060:22;;21032:262;;;21125:5;21119:2;21105:10;21125:5;21119:2;21105:10;:::i;:::-;21104:17;;;;:::i;:::-;:26;21100:194;;21153:46;16987:8;21169:2;21155:10;21160:5;21155:2;:10;:::i;:::-;21154:17;;;;:::i;:::-;:37;;;;:::i;:::-;21153:44;:46::i;:::-;21147:52;;21100:194;;;21239:43;16987:8;21250:5;21240:7;21245:2;21240;:7;:::i;:::-;:15;;;;:::i;21239:43::-;21232:50;;21100:194;21304:15;16939:8;21335:51;21356:22;16939:8;21356:4;:22;:::i;:::-;21380:5;:1;21384;21380:5;:::i;:::-;21335:20;:51::i;:::-;:69;;;;:::i;:::-;21304:100;;21494:33;21515:2;21519:7;21494:20;:33::i;:::-;21487:40;;;;;20445:1090;;;;;;;:::o;17812:125::-;17876:7;17903:26;17923:6;17911:8;17903:26;:::i;46656:177::-;46766:58;;;-1:-1:-1;;;;;27277:32:1;;46766:58:0;;;27259:51:1;27326:18;;;;27319:34;;;46766:58:0;;;;;;;;;;27232:18:1;;;;46766:58:0;;;;;;;;-1:-1:-1;;;;;46766:58:0;-1:-1:-1;;;46766:58:0;;;46739:86;;46759:5;;46739:19;:86::i;:::-;46656:177;;;:::o;22389:2659::-;22566:7;22599:1;22594:2;:6;22586:33;;;;-1:-1:-1;;;22586:33:0;;27566:2:1;22586:33:0;;;27548:21:1;27605:2;27585:18;;;27578:30;-1:-1:-1;;;27624:18:1;;;27617:44;27678:18;;22586:33:0;27364:338:1;22586:33:0;22634:5;22643:1;22634:10;22630:51;;-1:-1:-1;22668:1:0;22661:8;;22630:51;22697:1;22702;22697:6;22693:142;;22783:2;22750:30;22771:1;22774:5;22750:20;:30::i;:::-;:35;:73;;22793:30;22814:1;22817:5;22793:20;:30::i;:::-;22750:73;;;22788:2;22750:73;22743:80;;;;22693:142;16939:8;22851:1;:20;22847:701;;23158:12;;23202:11;23207:5;23202:1;:11;:::i;:::-;23185:28;;23232:6;23242:1;23232:11;23228:247;;23271:1;23264:8;;23228:247;;;23324:2;23314:6;23299:11;23324:2;23314:6;23299:11;:::i;:::-;23298:22;;;;:::i;:::-;:28;23294:181;;23371:7;23376:2;;23371:7;:::i;:::-;23355:11;23364:2;23355:6;:11;:::i;:::-;23354:25;;;;:::i;:::-;23347:32;;23294:181;;;23456:2;23450:1;23456:2;23427:12;23436:2;23427:5;:12;:::i;:::-;:19;;;;:::i;:::-;:25;;;;:::i;:::-;:32;;;;:::i;:::-;23420:39;;23294:181;23511:24;16939:8;23511:4;:24;:::i;:::-;23496:11;23502:4;23496:2;:11;:::i;:::-;:40;;;;:::i;:::-;23489:47;;;;;;22847:701;23872:13;23914:11;23919:5;23914:1;:11;:::i;:::-;23907:2;23900;23888:8;23907:2;23888:1;:8;:::i;:::-;:15;;;;:::i;:::-;:22;;;;:::i;:::-;:38;;;;:::i;:::-;23872:54;-1:-1:-1;23958:12:0;23998:2;23974:19;23992:1;16939:8;23974:19;:::i;:::-;23973:28;;;;:::i;:::-;23958:43;;24025:9;24057:5;24049:4;:13;24045:170;;24086:12;24093:5;24086:4;:12;:::i;:::-;24079:19;;24120:5;24113:12;;24045:170;;;24165:12;24173:4;24165:5;:12;:::i;:::-;24158:19;;24199:4;24192:11;;24045:170;24232:24;16939:8;24232:4;:24;:::i;:::-;24225:31;-1:-1:-1;24296:18:0;24317:85;24339:19;24357:1;16939:8;24339:19;:::i;:::-;24338:27;;24363:1;24338:27;:::i;:::-;24398:2;24367:27;24388:1;24391:2;24367:20;:27::i;:::-;:34;;;;:::i;:::-;24317:20;:85::i;:::-;24296:106;-1:-1:-1;24441:37:0;24296:106;24452:11;24459:4;;24452:11;:::i;24441:37::-;24428:50;-1:-1:-1;24539:19:0;24562;24580:1;16939:8;24562:19;:::i;:::-;24561:25;;24585:1;24561:25;:::i;:::-;24539:47;;24607:17;24639:4;24635:232;;;24672:17;24685:4;24672:10;:17;:::i;:::-;24660:29;;24708:9;24721:1;24708:14;24704:90;;24743:35;;-1:-1:-1;;;24743:35:0;;27909:2:1;24743:35:0;;;27891:21:1;27948:2;27928:18;;;27921:30;27987:27;27967:18;;;27960:55;28032:18;;24743:35:0;27707:349:1;24704:90:0;24635:232;;;24838:17;24845:10;24838:4;:17;:::i;:::-;24826:29;;24635:232;24879:10;24892:43;24912:9;24923:11;24892:19;:43::i;:::-;24879:56;;24955:2;24950;:7;24946:95;;;24981:1;24974:8;;;;;;;;;;;24946:95;25022:7;25027:2;25022;:7;:::i;:::-;25015:14;;;;;;;;;22389:2659;;;;;;;;:::o;19548:589::-;19708:7;19741:1;19736:2;:6;19728:33;;;;-1:-1:-1;;;19728:33:0;;27566:2:1;19728:33:0;;;27548:21:1;27605:2;27585:18;;;27578:30;-1:-1:-1;;;27624:18:1;;;27617:44;27678:18;;19728:33:0;27364:338:1;19728:33:0;19772:18;19798:7;19803:2;19798;:7;:::i;:::-;19793:13;;:1;:13;:::i;:::-;19772:34;;19832:1;19837;19832:6;19828:74;;19862:28;16939:8;19862:10;:28;:::i;:::-;19855:35;;;;;19828:74;19912:16;19931:38;19962:2;19952:7;19957:2;;19952:7;:::i;:::-;:12;;;;:::i;:::-;19966:2;19931:20;:38::i;:::-;19912:57;;19980:15;19998:33;20019:1;20022:8;19998:20;:33::i;:::-;19980:51;-1:-1:-1;16987:8:0;20100:10;19980:51;20067:19;20085:1;16939:8;20067:19;:::i;:::-;:29;;;;:::i;:::-;20066:44;;;;:::i;:::-;:63;;;;:::i;:::-;20059:70;19548:589;-1:-1:-1;;;;;;;;;19548:589:0:o;10211:1673::-;10259:7;10283:1;10288;10283:6;10279:47;;-1:-1:-1;10313:1:0;;10211:1673;-1:-1:-1;10211:1673:0:o;10279:47::-;11017:14;11051:1;11040:7;11045:1;11040:4;:7::i;:::-;:12;;11034:1;:19;;11017:36;;11519:1;11508:6;11504:1;:10;;;;;:::i;:::-;;11495:6;:19;11494:26;;11485:35;;11569:1;11558:6;11554:1;:10;;;;;:::i;:::-;;11545:6;:19;11544:26;;11535:35;;11619:1;11608:6;11604:1;:10;;;;;:::i;:::-;;11595:6;:19;11594:26;;11585:35;;11669:1;11658:6;11654:1;:10;;;;;:::i;:::-;;11645:6;:19;11644:26;;11635:35;;11719:1;11708:6;11704:1;:10;;;;;:::i;:::-;;11695:6;:19;11694:26;;11685:35;;11769:1;11758:6;11754:1;:10;;;;;:::i;:::-;;11745:6;:19;11744:26;;11735:35;;11819:1;11808:6;11804:1;:10;;;;;:::i;:::-;;11795:6;:19;11794:26;;11785:35;;11842:23;11846:6;11858;11854:1;:10;;;;;:::i;:::-;;11842:3;:23::i;51002:649::-;51426:23;51452:69;51480:4;51452:69;;;;;;;;;;;;;;;;;51460:5;-1:-1:-1;;;;;51452:27:0;;;:69;;;;;:::i;:::-;51426:95;;51540:10;:17;51561:1;51540:22;:56;;;;51577:10;51566:30;;;;;;;;;;;;:::i;:::-;51532:111;;;;-1:-1:-1;;;51532:111:0;;28513:2:1;51532:111:0;;;28495:21:1;28552:2;28532:18;;;28525:30;28591:34;28571:18;;;28564:62;-1:-1:-1;;;28642:18:1;;;28635:40;28692:19;;51532:111:0;28311:406:1;17670:134:0;17737:7;17764:32;17773:19;:6;17783:8;17773:19;:::i;:::-;17794:1;17764:8;:32::i;12361:1019::-;12413:7;;12500:3;12491:12;;;:16;12487:102;;12538:3;12528:13;;;;12560;12487:102;12616:2;12607:11;;;:15;12603:99;;12653:2;12643:12;;;;12674;12603:99;12729:2;12720:11;;;:15;12716:99;;12766:2;12756:12;;;;12787;12716:99;12842:2;12833:11;;;:15;12829:99;;12879:2;12869:12;;;;12900;12829:99;12955:1;12946:10;;;:14;12942:96;;12991:1;12981:11;;;;13011;12942:96;13065:1;13056:10;;;:14;13052:96;;13101:1;13091:11;;;;13121;13052:96;13175:1;13166:10;;;:14;13162:96;;13211:1;13201:11;;;;13231;13162:96;13285:1;13276:10;;;:14;13272:66;;13321:1;13311:11;13366:6;12361:1019;-1:-1:-1;;12361:1019:0:o;4143:106::-;4201:7;4232:1;4228;:5;:13;;4240:1;4228:13;;;-1:-1:-1;4236:1:0;;4143:106;-1:-1:-1;4143:106:0:o;40375:229::-;40512:12;40544:52;40566:6;40574:4;40580:1;40583:12;40512;41749;41763:23;41790:6;-1:-1:-1;;;;;41790:11:0;41809:5;41816:4;41790:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41748:73;;;;41839:69;41866:6;41874:7;41883:10;41895:12;41839:26;:69::i;:::-;41832:76;41461:455;-1:-1:-1;;;;;;;41461:455:0:o;44034:644::-;44219:12;44248:7;44244:427;;;44276:10;:17;44297:1;44276:22;44272:290;;-1:-1:-1;;;;;37915:19:0;;;44486:60;;;;-1:-1:-1;;;44486:60:0;;29623:2:1;44486:60:0;;;29605:21:1;29662:2;29642:18;;;29635:30;29701:31;29681:18;;;29674:59;29750:18;;44486:60:0;29421:353:1;44486:60:0;-1:-1:-1;44583:10:0;44576:17;;44244:427;44626:33;44634:10;44646:12;45381:17;;:21;45377:388;;45613:10;45607:17;45670:15;45657:10;45653:2;45649:19;45642:44;45377:388;45740:12;45733:20;;-1:-1:-1;;;45733:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;14:173:1:-;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;192:118;278:5;271:13;264:21;257:5;254:32;244:60;;300:1;297;290:12;315:815;443:6;451;459;467;475;483;491;499;507;560:3;548:9;539:7;535:23;531:33;528:53;;;577:1;574;567:12;528:53;600:29;619:9;600:29;:::i;:::-;590:39;;648:38;682:2;671:9;667:18;648:38;:::i;:::-;638:48;;705:38;739:2;728:9;724:18;705:38;:::i;:::-;695:48;;762:38;796:2;785:9;781:18;762:38;:::i;:::-;752:48;;847:3;836:9;832:19;819:33;809:43;;899:3;888:9;884:19;871:33;861:43;;951:3;940:9;936:19;923:33;913:43;;1003:3;992:9;988:19;975:33;965:43;;1058:3;1047:9;1043:19;1030:33;1072:28;1094:5;1072:28;:::i;:::-;1119:5;1109:15;;;315:815;;;;;;;;;;;:::o;1135:250::-;1220:1;1230:113;1244:6;1241:1;1238:13;1230:113;;;1320:11;;;1314:18;1301:11;;;1294:39;1266:2;1259:10;1230:113;;;-1:-1:-1;;1377:1:1;1359:16;;1352:27;1135:250::o;1390:396::-;1539:2;1528:9;1521:21;1502:4;1571:6;1565:13;1614:6;1609:2;1598:9;1594:18;1587:34;1630:79;1702:6;1697:2;1686:9;1682:18;1677:2;1669:6;1665:15;1630:79;:::i;:::-;1770:2;1749:15;-1:-1:-1;;1745:29:1;1730:45;;;;1777:2;1726:54;;1390:396;-1:-1:-1;;1390:396:1:o;1791:254::-;1859:6;1867;1920:2;1908:9;1899:7;1895:23;1891:32;1888:52;;;1936:1;1933;1926:12;1888:52;1959:29;1978:9;1959:29;:::i;:::-;1949:39;2035:2;2020:18;;;;2007:32;;-1:-1:-1;;;1791:254:1:o;2242:186::-;2301:6;2354:2;2342:9;2333:7;2329:23;2325:32;2322:52;;;2370:1;2367;2360:12;2322:52;2393:29;2412:9;2393:29;:::i;2615:328::-;2692:6;2700;2708;2761:2;2749:9;2740:7;2736:23;2732:32;2729:52;;;2777:1;2774;2767:12;2729:52;2800:29;2819:9;2800:29;:::i;:::-;2790:39;;2848:38;2882:2;2871:9;2867:18;2848:38;:::i;:::-;2838:48;;2933:2;2922:9;2918:18;2905:32;2895:42;;2615:328;;;;;:::o;4325:127::-;4386:10;4381:3;4377:20;4374:1;4367:31;4417:4;4414:1;4407:15;4441:4;4438:1;4431:15;4457:234;4535:1;4528:5;4525:12;4515:143;;4580:10;4575:3;4571:20;4568:1;4561:31;4615:4;4612:1;4605:15;4643:4;4640:1;4633:15;4515:143;4667:18;;4457:234::o;4696:416::-;4936:25;;;4992:2;4977:18;;4970:34;;;4923:3;4908:19;;5013:50;5059:2;5044:18;;5036:6;5013:50;:::i;:::-;5099:6;5094:2;5083:9;5079:18;5072:34;4696:416;;;;;;;:::o;5117:180::-;5176:6;5229:2;5217:9;5208:7;5204:23;5200:32;5197:52;;;5245:1;5242;5235:12;5197:52;-1:-1:-1;5268:23:1;;5117:180;-1:-1:-1;5117:180:1:o;5718:672::-;5862:4;5904:3;5893:9;5889:19;5881:27;;5941:6;5935:13;5924:9;5917:32;6005:4;5997:6;5993:17;5987:24;5980:4;5969:9;5965:20;5958:54;6068:4;6060:6;6056:17;6050:24;6043:4;6032:9;6028:20;6021:54;6131:4;6123:6;6119:17;6113:24;6106:4;6095:9;6091:20;6084:54;6194:4;6186:6;6182:17;6176:24;6169:4;6158:9;6154:20;6147:54;6257:4;6249:6;6245:17;6239:24;6232:4;6221:9;6217:20;6210:54;6311:4;6303:6;6299:17;6293:24;6326:58;6378:4;6367:9;6363:20;6349:12;6326:58;:::i;:::-;;5718:672;;;;:::o;6395:347::-;6446:8;6456:6;6510:3;6503:4;6495:6;6491:17;6487:27;6477:55;;6528:1;6525;6518:12;6477:55;-1:-1:-1;6551:20:1;;6594:18;6583:30;;6580:50;;;6626:1;6623;6616:12;6580:50;6663:4;6655:6;6651:17;6639:29;;6715:3;6708:4;6699:6;6691;6687:19;6683:30;6680:39;6677:59;;;6732:1;6729;6722:12;6747:758;6862:6;6870;6878;6886;6894;6902;6910;6963:3;6951:9;6942:7;6938:23;6934:33;6931:53;;;6980:1;6977;6970:12;6931:53;7016:9;7003:23;6993:33;;7045:38;7079:2;7068:9;7064:18;7045:38;:::i;:::-;7035:48;;7130:2;7119:9;7115:18;7102:32;7092:42;;7181:2;7170:9;7166:18;7153:32;7143:42;;7236:3;7225:9;7221:19;7208:33;7264:18;7256:6;7253:30;7250:50;;;7296:1;7293;7286:12;7250:50;7335:58;7385:7;7376:6;7365:9;7361:22;7335:58;:::i;:::-;6747:758;;;;-1:-1:-1;6747:758:1;;;;;;7494:3;7479:19;;;7466:33;;6747:758;-1:-1:-1;;;;6747:758:1:o;7510:620::-;7607:6;7615;7623;7631;7639;7692:3;7680:9;7671:7;7667:23;7663:33;7660:53;;;7709:1;7706;7699:12;7660:53;7745:9;7732:23;7722:33;;7802:2;7791:9;7787:18;7774:32;7764:42;;7825:38;7859:2;7848:9;7844:18;7825:38;:::i;:::-;7815:48;;7914:2;7903:9;7899:18;7886:32;7941:18;7933:6;7930:30;7927:50;;;7973:1;7970;7963:12;7927:50;8012:58;8062:7;8053:6;8042:9;8038:22;8012:58;:::i;:::-;7510:620;;;;-1:-1:-1;7510:620:1;;-1:-1:-1;8089:8:1;;7986:84;7510:620;-1:-1:-1;;;7510:620:1:o;8135:114::-;8219:4;8212:5;8208:16;8201:5;8198:27;8188:55;;8239:1;8236;8229:12;8254:667;8365:6;8373;8381;8389;8397;8405;8413;8466:3;8454:9;8445:7;8441:23;8437:33;8434:53;;;8483:1;8480;8473:12;8434:53;8506:29;8525:9;8506:29;:::i;:::-;8496:39;;8554:38;8588:2;8577:9;8573:18;8554:38;:::i;:::-;8544:48;;8639:2;8628:9;8624:18;8611:32;8601:42;;8690:2;8679:9;8675:18;8662:32;8652:42;;8744:3;8733:9;8729:19;8716:33;8758:29;8781:5;8758:29;:::i;:::-;8254:667;;;;-1:-1:-1;8254:667:1;;;;8806:5;8858:3;8843:19;;8830:33;;-1:-1:-1;8910:3:1;8895:19;;;8882:33;;8254:667;-1:-1:-1;;8254:667:1:o;8926:260::-;8994:6;9002;9055:2;9043:9;9034:7;9030:23;9026:32;9023:52;;;9071:1;9068;9061:12;9023:52;9094:29;9113:9;9094:29;:::i;:::-;9084:39;;9142:38;9176:2;9165:9;9161:18;9142:38;:::i;:::-;9132:48;;8926:260;;;;;:::o;10502:703::-;10729:3;10767:6;10761:13;10783:66;10842:6;10837:3;10830:4;10822:6;10818:17;10783:66;:::i;:::-;10912:13;;10871:16;;;;10934:70;10912:13;10871:16;10981:4;10969:17;;10934:70;:::i;:::-;11071:13;;11026:20;;;11093:70;11071:13;11026:20;11140:4;11128:17;;11093:70;:::i;:::-;11179:20;;10502:703;-1:-1:-1;;;;;10502:703:1:o;11210:127::-;11271:10;11266:3;11262:20;11259:1;11252:31;11302:4;11299:1;11292:15;11326:4;11323:1;11316:15;11342:380;11421:1;11417:12;;;;11464;;;11485:61;;11539:4;11531:6;11527:17;11517:27;;11485:61;11592:2;11584:6;11581:14;11561:18;11558:38;11555:161;;11638:10;11633:3;11629:20;11626:1;11619:31;11673:4;11670:1;11663:15;11701:4;11698:1;11691:15;11555:161;;11342:380;;;:::o;11853:545::-;11955:2;11950:3;11947:11;11944:448;;;11991:1;12016:5;12012:2;12005:17;12061:4;12057:2;12047:19;12131:2;12119:10;12115:19;12112:1;12108:27;12102:4;12098:38;12167:4;12155:10;12152:20;12149:47;;;-1:-1:-1;12190:4:1;12149:47;12245:2;12240:3;12236:12;12233:1;12229:20;12223:4;12219:31;12209:41;;12300:82;12318:2;12311:5;12308:13;12300:82;;;12363:17;;;12344:1;12333:13;12300:82;;;12304:3;;;11853:545;;;:::o;12574:1352::-;12700:3;12694:10;12727:18;12719:6;12716:30;12713:56;;;12749:18;;:::i;:::-;12778:97;12868:6;12828:38;12860:4;12854:11;12828:38;:::i;:::-;12822:4;12778:97;:::i;:::-;12930:4;;12994:2;12983:14;;13011:1;13006:663;;;;13713:1;13730:6;13727:89;;;-1:-1:-1;13782:19:1;;;13776:26;13727:89;-1:-1:-1;;12531:1:1;12527:11;;;12523:24;12519:29;12509:40;12555:1;12551:11;;;12506:57;13829:81;;12976:944;;13006:663;11800:1;11793:14;;;11837:4;11824:18;;-1:-1:-1;;13042:20:1;;;13160:236;13174:7;13171:1;13168:14;13160:236;;;13263:19;;;13257:26;13242:42;;13355:27;;;;13323:1;13311:14;;;;13190:19;;13160:236;;;13164:3;13424:6;13415:7;13412:19;13409:201;;;13485:19;;;13479:26;-1:-1:-1;;13568:1:1;13564:14;;;13580:3;13560:24;13556:37;13552:42;13537:58;13522:74;;13409:201;-1:-1:-1;;;;;13656:1:1;13640:14;;;13636:22;13623:36;;-1:-1:-1;12574:1352:1:o;13931:247::-;13999:6;14052:2;14040:9;14031:7;14027:23;14023:32;14020:52;;;14068:1;14065;14058:12;14020:52;14100:9;14094:16;14119:29;14142:5;14119:29;:::i;14183:127::-;14244:10;14239:3;14235:20;14232:1;14225:31;14275:4;14272:1;14265:15;14299:4;14296:1;14289:15;14315:125;14380:9;;;14401:10;;;14398:36;;;14414:18;;:::i;14445:127::-;14506:10;14501:3;14497:20;14494:1;14487:31;14537:4;14534:1;14527:15;14561:4;14558:1;14551:15;14577:168;14617:7;14683:1;14679;14675:6;14671:14;14668:1;14665:21;14660:1;14653:9;14646:17;14642:45;14639:71;;;14690:18;;:::i;:::-;-1:-1:-1;14730:9:1;;14577:168::o;14750:135::-;14789:3;14810:17;;;14807:43;;14830:18;;:::i;:::-;-1:-1:-1;14877:1:1;14866:13;;14750:135::o;15586:128::-;15653:9;;;15674:11;;;15671:37;;;15688:18;;:::i;15719:184::-;15789:6;15842:2;15830:9;15821:7;15817:23;15813:32;15810:52;;;15858:1;15855;15848:12;15810:52;-1:-1:-1;15881:16:1;;15719:184;-1:-1:-1;15719:184:1:o;17994:127::-;18055:10;18050:3;18046:20;18043:1;18036:31;18086:4;18083:1;18076:15;18110:4;18107:1;18100:15;18126:217;18166:1;18192;18182:132;;18236:10;18231:3;18227:20;18224:1;18217:31;18271:4;18268:1;18261:15;18299:4;18296:1;18289:15;18182:132;-1:-1:-1;18328:9:1;;18126:217::o;19727:266::-;19815:6;19810:3;19803:19;19867:6;19860:5;19853:4;19848:3;19844:14;19831:43;-1:-1:-1;19919:1:1;19894:16;;;19912:4;19890:27;;;19883:38;;;;19975:2;19954:15;;;-1:-1:-1;;19950:29:1;19941:39;;;19937:50;;19727:266::o;19998:557::-;20296:1;20292;20287:3;20283:11;20279:19;20271:6;20267:32;20256:9;20249:51;20336:6;20331:2;20320:9;20316:18;20309:34;20379:6;20374:2;20363:9;20359:18;20352:34;20422:6;20417:2;20406:9;20402:18;20395:34;20466:3;20460;20449:9;20445:19;20438:32;20230:4;20487:62;20544:3;20533:9;20529:19;20521:6;20513;20487:62;:::i;:::-;20479:70;19998:557;-1:-1:-1;;;;;;;;19998:557:1:o;21702:331::-;21904:2;21886:21;;;21943:1;21923:18;;;21916:29;-1:-1:-1;;;21976:2:1;21961:18;;21954:38;22024:2;22009:18;;21702:331::o;22038:202::-;22181:2;22166:18;;22193:41;22170:9;22216:6;22193:41;:::i;22245:609::-;-1:-1:-1;;;;;22588:15:1;;;22570:34;;22640:15;;;22635:2;22620:18;;22613:43;22687:2;22672:18;;22665:34;;;;22730:2;22715:18;;22708:34;;;;22779:15;;22773:3;22758:19;;22751:44;22832:15;;;22550:3;22811:19;;22804:44;22519:3;22504:19;;22245:609::o;22859:485::-;23129:1;23125;23120:3;23116:11;23112:19;23104:6;23100:32;23089:9;23082:51;23169:6;23164:2;23153:9;23149:18;23142:34;23212:6;23207:2;23196:9;23192:18;23185:34;23255:3;23250:2;23239:9;23235:18;23228:31;23063:4;23276:62;23333:3;23322:9;23318:19;23310:6;23302;23276:62;:::i;23349:341::-;23551:2;23533:21;;;23590:2;23570:18;;;23563:30;-1:-1:-1;;;23624:2:1;23609:18;;23602:47;23681:2;23666:18;;23349:341::o;28061:245::-;28128:6;28181:2;28169:9;28160:7;28156:23;28152:32;28149:52;;;28197:1;28194;28187:12;28149:52;28229:9;28223:16;28248:28;28270:5;28248:28;:::i;29129:287::-;29258:3;29296:6;29290:13;29312:66;29371:6;29366:3;29359:4;29351:6;29347:17;29312:66;:::i;:::-;29394:16;;;;;29129:287;-1:-1:-1;;29129:287:1:o

Swarm Source

ipfs://f3687e01d102b5cdb36d7d8bacce721c475ea34f78cb33a0180d425c383b574c

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

A WBTC-FBTC liquidity pool on DODO

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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