ETH Price: $3,323.88 (+1.60%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
x5Repricer

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 12 : x5Repricer.sol
// "SPDX-License-Identifier: GNU General Public License v3.0"

pragma solidity 0.7.6;

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./IRepricer.sol";
import "../Const.sol";
import "../Num.sol";
import "../NumExtra.sol";

//import "hardhat/console.sol";

contract x5Repricer is IRepricer,  Const, Num, NumExtra {
    int public constant NEGATIVE_INFINITY = type(int256).min;

    function isRepricer() external override pure returns(bool) {
        return true;
    }

    function symbol() external override pure returns (string memory) {
        return "x5Repricer";
    }

    function reprice(
        uint pMin,
        int volatility,
        IVault _vault,
        uint[2] memory primary,
        uint[2] memory complement,
        int _liveUnderlingValue
    )
    external view override returns(
        uint newPrimaryLeverage, uint newComplementLeverage, int estPricePrimary, int estPriceComplement
    ) {

        require(address(_vault) != address(0), "Zero oracle");

        (estPricePrimary, estPriceComplement) = calcEstPrice(
            calcDenomination(_vault),
            calcUnv(
                _liveUnderlingValue,
                getCurrentUnderlingValue(_vault)
            ),
            calcTtm(_vault.settleTime()),
            int(pMin),
            volatility
        );
        uint estPrice = uint(estPriceComplement * iBONE / estPricePrimary);

        uint leveragesMultiplied = mul(primary[1], complement[1]);

        newPrimaryLeverage = uint(sqrt(
                int(div(
                    mul(leveragesMultiplied, mul(complement[0], estPrice)),
                    primary[0]
                )))
        );
        newComplementLeverage = div(leveragesMultiplied, newPrimaryLeverage);
    }

    function getCurrentUnderlingValue(IVault _vault)
    internal view returns(int currentUnderlingValue) {
        uint currentTimestamp;
        (,currentUnderlingValue,,currentTimestamp,) = AggregatorV3Interface(_vault.oracles(0)).latestRoundData();
        require(currentTimestamp > 0, "EMPTY_ORACLE_LATEST_ROUND");
    }

    function calcTtm(uint _settledTimestamp)
    internal view returns(int) {
        return (int(_settledTimestamp) - int(block.timestamp)) * iBONE / 31536000; // 365 * 24 * 3600
    }

    function calcUnv(int _liveUnderlingValue, int _currentUnderlingValue)
    internal pure returns(int) {
        return 5 * iBONE + 5 * ((_currentUnderlingValue - _liveUnderlingValue) * iBONE / _liveUnderlingValue);
    }

    function calcDenomination(IVault _vault) internal view returns (int denomination) {
        denomination = int(
            _vault.derivativeSpecification().primaryNominalValue() +
            _vault.derivativeSpecification().complementNominalValue()
        );
    }

    function calcEstPricePrimary(
        int _unvPrim,
        int _ttm,
        int _volatility
    ) internal pure returns(int256) {
        int volatilityBySqrtTtm = _volatility * sqrt(_ttm) / iBONE;
        int multiplier = (iBONE * iBONE) / volatilityBySqrtTtm;
        int volatilityByTtm = (_volatility * _volatility) * _ttm / (iBONE * iBONE * 2);

        int d1 = multiplier  * (ln(_unvPrim/4) + volatilityByTtm) / iBONE;
        int option4 = ncdf(d1) * _unvPrim / iBONE - ncdf(d1 - volatilityBySqrtTtm) * 4;

        d1 = multiplier  * (ln(_unvPrim/6) +  volatilityByTtm) / iBONE;
        int option6 = ncdf(d1) * _unvPrim / iBONE - ncdf(d1 - volatilityBySqrtTtm) * 6;

        return option4 - option6;
    }

    function calcEstPrice(
        int _denomination,
        int _unvPrim,
        int _ttm,
        int _pMin,
        int _volatility
    )
    internal pure returns(int estPricePrimary, int estPriceComplement)
    {
        estPricePrimary = calcEstPricePrimary(_unvPrim, _ttm, _volatility);

        if(estPricePrimary < _pMin) {
            estPricePrimary = _pMin;
        }

        int denominationTimesBone = _denomination * iBONE;
        if(estPricePrimary > denominationTimesBone - _pMin) {
            estPricePrimary = denominationTimesBone - _pMin;
        }

        estPriceComplement = denominationTimesBone - estPricePrimary;
    }
}

File 2 of 12 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;

interface AggregatorV3Interface {

  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}

File 3 of 12 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

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

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

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

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

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

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

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

File 4 of 12 : IRepricer.sol
// "SPDX-License-Identifier: GNU General Public License v3.0"

pragma solidity 0.7.6;

import "../IVault.sol";

interface IRepricer {

    function isRepricer() external pure returns(bool);

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

    function reprice(
        uint _pMin,
        int _volatility,
        IVault _vault,
        uint[2] memory _primary,
        uint[2] memory _complement,
        int _liveUnderlingValue
    )
    external view returns(
        uint newPrimaryLeverage, uint newComplementLeverage, int estPricePrimary, int estPriceComplement
    );
}

File 5 of 12 : Const.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Color.sol";

contract Const is Bronze {
    uint public constant BONE              = 10**18;
    int public constant  iBONE             = int(BONE);

    uint public constant MIN_POW_BASE      = 1 wei;
    uint public constant MAX_POW_BASE      = (2 * BONE) - 1 wei;
    uint public constant POW_PRECISION     = BONE / 10**10;

    uint public constant MAX_IN_RATIO      = BONE / 2;
    uint public constant MAX_OUT_RATIO     = (BONE / 3) + 1 wei;
}

File 6 of 12 : Num.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Const.sol";

contract Num is Const {

    function toi(uint a)
        internal pure
        returns (uint)
    {
        return a / BONE;
    }

    function floor(uint a)
        internal pure
        returns (uint)
    {
        return toi(a) * BONE;
    }

    function add(uint a, uint b)
        internal pure
        returns (uint c)
    {
        c = a + b;
        require(c >= a, "ADD_OVERFLOW");
    }

    function sub(uint a, uint b)
        internal pure
        returns (uint c)
    {
        bool flag;
        (c, flag) = subSign(a, b);
        require(!flag, "SUB_UNDERFLOW");
    }

    function subSign(uint a, uint b)
        internal pure
        returns (uint, bool)
    {
        if (a >= b) {
            return (a - b, false);
        } else {
            return (b - a, true);
        }
    }

    function mul(uint a, uint b)
        internal pure
        returns (uint c)
    {
        uint c0 = a * b;
        require(a == 0 || c0 / a == b, "MUL_OVERFLOW");
        uint c1 = c0 + (BONE / 2);
        require(c1 >= c0, "MUL_OVERFLOW");
        c = c1 / BONE;
    }

    function div(uint a, uint b)
        internal pure
        returns (uint c)
    {
        require(b != 0, "DIV_ZERO");
        uint c0 = a * BONE;
        require(a == 0 || c0 / a == BONE, "DIV_INTERNAL"); // mul overflow
        uint c1 = c0 + (b / 2);
        require(c1 >= c0, "DIV_INTERNAL"); //  add require
        c = c1 / b;
    }

    // DSMath.wpow
    function powi(uint a, uint n)
        internal pure
        returns (uint z)
    {
        z = n % 2 != 0 ? a : BONE;

        for (n /= 2; n != 0; n /= 2) {
            a = mul(a, a);

            if (n % 2 != 0) {
                z = mul(z, a);
            }
        }
    }

    // Compute b^(e.w) by splitting it into (b^e)*(b^0.w).
    // Use `powi` for `b^e` and `powK` for k iterations
    // of approximation of b^0.w
    function pow(uint base, uint exp)
        internal pure
        returns (uint)
    {
        require(base >= MIN_POW_BASE, "POW_BASE_TOO_LOW");
        require(base <= MAX_POW_BASE, "POW_BASE_TOO_HIGH");

        uint whole  = floor(exp);
        uint remain = sub(exp, whole);

        uint wholePow = powi(base, toi(whole));

        if (remain == 0) {
            return wholePow;
        }

        uint partialResult = powApprox(base, remain, POW_PRECISION);
        return mul(wholePow, partialResult);
    }

    function powApprox(uint base, uint exp, uint precision)
        internal pure
        returns (uint sum)
    {
        // term 0:
        uint a     = exp;
        (uint x, bool xneg)  = subSign(base, BONE);
        uint term = BONE;
        sum   = term;
        bool negative = false;


        // term(k) = numer / denom
        //         = (product(a - i - 1, i=1-->k) * x^k) / (k!)
        // each iteration, multiply previous term by (a-(k-1)) * x / k
        // continue until term is less than precision
        for (uint i = 1; term >= precision; i++) {
            uint bigK = i * BONE;
            (uint c, bool cneg) = subSign(a, sub(bigK, BONE));
            term = mul(term, mul(c, x));
            term = div(term, bigK);
            if (term == 0) break;

            if (xneg) negative = !negative;
            if (cneg) negative = !negative;
            if (negative) {
                sum = sub(sum, term);
            } else {
                sum = add(sum, term);
            }
        }
    }

    function min(uint first, uint second)
        internal pure
        returns (uint)
    {
        if(first < second) {
            return first;
        }
        return second;
    }
}

File 7 of 12 : NumExtra.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "abdk-libraries-solidity/ABDKMathQuad.sol";
import "./Const.sol";

contract NumExtra is Const {
    function toIntMultiplied(bytes16 value, uint256 bone)
    internal pure
    returns(int256)
    {
        return ABDKMathQuad.toInt(ABDKMathQuad.mul(value, ABDKMathQuad.fromUInt(bone)));
    }

    function fromIntMultiplied(int256 value, uint256 bone)
    internal pure
    returns(bytes16)
    {
        return ABDKMathQuad.div(ABDKMathQuad.fromInt(value), ABDKMathQuad.fromUInt(bone));
    }

    function ln(int256 x) public pure returns(int256) {
        return toIntMultiplied(
            ABDKMathQuad.ln(fromIntMultiplied(x, BONE)),
            BONE
        );
    }

    function sqrt(int256 x) public pure returns(int256) {
        return toIntMultiplied(
            ABDKMathQuad.sqrt(fromIntMultiplied(x, BONE)),
            BONE
        );
    }

    function powi(bytes16 a, uint n)
    internal pure
    returns (bytes16)
    {
        bytes16 z = n % 2 != 0 ? a : ABDKMathQuad.fromInt(1);

        for (n /= 2; n != 0; n /= 2) {
            a = ABDKMathQuad.mul(a, a);

            if (n % 2 != 0) {
                z = ABDKMathQuad.mul(z, a);
            }
        }
        return z;
    }

    // https://stackoverflow.com/questions/2328258/cumulative-normal-distribution-function-in-c-c/23119456#23119456
    function ncdf(int x)
    public pure
    returns (int256)
    {
        bytes16 xq = fromIntMultiplied(x, BONE);

        bytes16 z = ABDKMathQuad.abs(xq);
        bytes16 c = 0x00000000000000000000000000000000;

        if(ABDKMathQuad.cmp(z, ABDKMathQuad.fromUInt(37)) == int8(-1) || ABDKMathQuad.eq(z, ABDKMathQuad.fromUInt(37)) )
        {
            bytes16 e = ABDKMathQuad.exp(
                ABDKMathQuad.div(
                    ABDKMathQuad.mul(ABDKMathQuad.neg(z), z),
                    ABDKMathQuad.fromUInt(2)
                )
            );

            if(ABDKMathQuad.cmp(z, fromIntMultiplied(707106781186547, 10**14)) == int8(-1))
            {
                c = one(z, e);
            } else {
                c = two(z, e);
            }
        }
        c = (ABDKMathQuad.sign(xq) == int8(-1) || ABDKMathQuad.eq(xq, 0)) ? c : ABDKMathQuad.sub(ABDKMathQuad.fromUInt(1), c);
        return toIntMultiplied(c, BONE);
    }

    function one(bytes16 z, bytes16 e)
    internal pure
    returns (bytes16)
    {
        bytes16 n = addm(
            addm(
                addm(
                    addm(
                        addm(
                            addm(fromIntMultiplied(352624965998911, 10**16), z, fromIntMultiplied(700383064443688, 10**15)),
                            z, fromIntMultiplied(637396220353165, 10**14)),
                        z, fromIntMultiplied(33912866078383, 10**12)),
                    z, fromIntMultiplied(112079291497871, 10**12)),
                z, fromIntMultiplied(221213596169931, 10**12)),
            z, fromIntMultiplied(220206867912376, 10**12)
        );
        bytes16 d = addm(
            addm(
                addm(
                    addm(
                        addm(
                            addm(
                                addm(fromIntMultiplied(883883476483184, 10**16), z, fromIntMultiplied(175566716318264, 10**14)),
                                z, fromIntMultiplied(16064177579207, 10**12)),
                            z, fromIntMultiplied(867807322029461, 10**13)),
                        z, fromIntMultiplied(296564248779674, 10**12)),
                    z, fromIntMultiplied(637333633378831, 10**12)),
                z, fromIntMultiplied(793826512519948, 10**12)),
            z, fromIntMultiplied(440413735824752, 10**12));

        return ABDKMathQuad.div(ABDKMathQuad.mul(e, n), d);
    }

    function two(bytes16 z, bytes16 e)
    internal pure
    returns (bytes16)
    {
        bytes16 f = addr(z, ABDKMathQuad.fromUInt(13), ABDKMathQuad.fromUInt(20));
        f =  addr(z, ABDKMathQuad.fromUInt(4), f);
        f =  addr(z, ABDKMathQuad.fromUInt(3), f);
        f =  addr(z, ABDKMathQuad.fromUInt(2), f);
        f =  addr(z, ABDKMathQuad.fromUInt(1), f);

        return ABDKMathQuad.div(e, ABDKMathQuad.div(fromIntMultiplied(250662827463, 10**11), f)); // sqrt(4.0*acos(0.0))
    }

    function addm(bytes16 a, bytes16 b, bytes16 c)
    internal pure
    returns (bytes16)
    {
        return ABDKMathQuad.add(ABDKMathQuad.mul(a, b), c);
    }

    function addr(bytes16 a, bytes16 b, bytes16 c)
    internal pure
    returns (bytes16)
    {
        return ABDKMathQuad.add(a, ABDKMathQuad.div(b, c));
    }
}

File 8 of 12 : IVault.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Token.sol";
import "./libs/complifi/IDerivativeSpecification.sol";

interface IVault {
    /// @notice vault initialization time
    function initializationTime() external view returns(uint256);
    /// @notice start of live period
    function liveTime() external view returns(uint256);
    /// @notice end of live period
    function settleTime() external view returns(uint256);

    /// @notice underlying value at the start of live period
    function underlyingStarts(uint index) external view returns(int256);
    /// @notice underlying value at the end of live period
    function underlyingEnds(uint index) external view returns(int256);

    /// @notice primary token conversion rate multiplied by 10 ^ 12
    function primaryConversion() external view returns(uint256);
    /// @notice complement token conversion rate multiplied by 10 ^ 12
    function complementConversion() external view returns(uint256);

    // @notice derivative specification address
    function derivativeSpecification() external view returns(IDerivativeSpecification);
    // @notice collateral token address
    function collateralToken() external view returns(IERC20);
    // @notice oracle address
    function oracles(uint index) external view returns(address);
    function oracleIterators(uint index) external view returns(address);

    // @notice primary token address
    function primaryToken() external view returns(IERC20);
    // @notice complement token address
    function complementToken() external view returns(IERC20);
}

File 9 of 12 : Token.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Num.sol";

// Highly opinionated token implementation

interface IERC20 {

    function totalSupply() external view returns (uint);
    function balanceOf(address whom) external view returns (uint);
    function allowance(address src, address dst) external view returns (uint);

    function approve(address dst, uint amt) external returns (bool);
    function transfer(address dst, uint amt) external returns (bool);
    function transferFrom(
        address src, address dst, uint amt
    ) external returns (bool);
}

contract TokenBase is Num {

    mapping(address => uint)                   internal _balance;
    mapping(address => mapping(address=>uint)) internal _allowance;
    uint internal _totalSupply;

    event Approval(address indexed src, address indexed dst, uint amt);
    event Transfer(address indexed src, address indexed dst, uint amt);

    function _mint(uint amt) internal {
        _balance[address(this)] = add(_balance[address(this)], amt);
        _totalSupply = add(_totalSupply, amt);
        emit Transfer(address(0), address(this), amt);
    }

    function _burn(uint amt) internal {
        require(_balance[address(this)] >= amt, "INSUFFICIENT_BAL");
        _balance[address(this)] = sub(_balance[address(this)], amt);
        _totalSupply = sub(_totalSupply, amt);
        emit Transfer(address(this), address(0), amt);
    }

    function _move(address src, address dst, uint amt) internal {
        require(_balance[src] >= amt, "INSUFFICIENT_BAL");
        _balance[src] = sub(_balance[src], amt);
        _balance[dst] = add(_balance[dst], amt);
        emit Transfer(src, dst, amt);
    }

    function _push(address to, uint amt) internal {
        _move(address(this), to, amt);
    }

    function _pull(address from, uint amt) internal {
        _move(from, address(this), amt);
    }
}

contract Token is TokenBase, IERC20 {

    string  private _name;
    string  private _symbol;
    uint8   private constant _decimals = 18;

    function setName(string memory name) internal {
        _name = name;
    }

    function setSymbol(string memory symbol) internal {
        _symbol = symbol;
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns(uint8) {
        return _decimals;
    }

    function allowance(address src, address dst) external view override returns (uint) {
        return _allowance[src][dst];
    }

    function balanceOf(address whom) external view override returns (uint) {
        return _balance[whom];
    }

    function totalSupply() public view override returns (uint) {
        return _totalSupply;
    }

    function approve(address dst, uint amt) external override returns (bool) {
        _allowance[msg.sender][dst] = amt;
        emit Approval(msg.sender, dst, amt);
        return true;
    }

    function increaseApproval(address dst, uint amt) external returns (bool) {
        _allowance[msg.sender][dst] = add(_allowance[msg.sender][dst], amt);
        emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
        return true;
    }

    function decreaseApproval(address dst, uint amt) external returns (bool) {
        uint oldValue = _allowance[msg.sender][dst];
        if (amt > oldValue) {
            _allowance[msg.sender][dst] = 0;
        } else {
            _allowance[msg.sender][dst] = sub(oldValue, amt);
        }
        emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
        return true;
    }

    function transfer(address dst, uint amt) external override returns (bool) {
        _move(msg.sender, dst, amt);
        return true;
    }

    function transferFrom(address src, address dst, uint amt) external override returns (bool) {
        uint oldValue = _allowance[src][msg.sender];
        require(msg.sender == src || amt <= oldValue, "TOKEN_BAD_CALLER");
        _move(src, dst, amt);
        if (msg.sender != src && oldValue != uint256(-1)) {
            _allowance[src][msg.sender] = sub(oldValue, amt);
            emit Approval(msg.sender, dst, _allowance[src][msg.sender]);
        }
        return true;
    }
}

File 10 of 12 : IDerivativeSpecification.sol
// "SPDX-License-Identifier: GPL-3.0-or-later"

pragma solidity 0.7.6;

/// @title Derivative Specification interface
/// @notice Immutable collection of derivative attributes
/// @dev Created by the derivative's author and published to the DerivativeSpecificationRegistry
interface IDerivativeSpecification {
    /// @notice Proof of a derivative specification
    /// @dev Verifies that contract is a derivative specification
    /// @return true if contract is a derivative specification
    function isDerivativeSpecification() external pure returns (bool);

    /// @notice Set of oracles that are relied upon to measure changes in the state of the world
    /// between the start and the end of the Live period
    /// @dev Should be resolved through OracleRegistry contract
    /// @return oracle symbols
    function oracleSymbols() external view returns (bytes32[] memory);

    /// @notice Algorithm that, for the type of oracle used by the derivative,
    /// finds the value closest to a given timestamp
    /// @dev Should be resolved through OracleIteratorRegistry contract
    /// @return oracle iterator symbols
    function oracleIteratorSymbols() external view returns (bytes32[] memory);

    /// @notice Type of collateral that users submit to mint the derivative
    /// @dev Should be resolved through CollateralTokenRegistry contract
    /// @return collateral token symbol
    function collateralTokenSymbol() external view returns (bytes32);

    /// @notice Mapping from the change in the underlying variable (as defined by the oracle)
    /// and the initial collateral split to the final collateral split
    /// @dev Should be resolved through CollateralSplitRegistry contract
    /// @return collateral split symbol
    function collateralSplitSymbol() external view returns (bytes32);

    /// @notice Lifecycle parameter that define the length of the derivative's Live period.
    /// @dev Set in seconds
    /// @return live period value
    function livePeriod() external view returns (uint256);

    /// @notice Parameter that determines starting nominal value of primary asset
    /// @dev Units of collateral theoretically swappable for 1 unit of primary asset
    /// @return primary nominal value
    function primaryNominalValue() external view returns (uint256);

    /// @notice Parameter that determines starting nominal value of complement asset
    /// @dev Units of collateral theoretically swappable for 1 unit of complement asset
    /// @return complement nominal value
    function complementNominalValue() external view returns (uint256);

    /// @notice Minting fee rate due to the author of the derivative specification.
    /// @dev Percentage fee multiplied by 10 ^ 12
    /// @return author fee
    function authorFee() external view returns (uint256);

    /// @notice Symbol of the derivative
    /// @dev Should be resolved through DerivativeSpecificationRegistry contract
    /// @return derivative specification symbol
    function symbol() external view returns (string memory);

    /// @notice Return optional long name of the derivative
    /// @dev Isn't used directly in the protocol
    /// @return long name
    function name() external view returns (string memory);

    /// @notice Optional URI to the derivative specs
    /// @dev Isn't used directly in the protocol
    /// @return URI to the derivative specs
    function baseURI() external view returns (string memory);

    /// @notice Derivative spec author
    /// @dev Used to set and receive author's fee
    /// @return address of the author
    function author() external view returns (address);
}

File 11 of 12 : Color.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

abstract contract Color {
    function getColor()
        external view virtual
        returns (bytes32);
}

contract Bronze is Color {
    function getColor()
        external view override
        returns (bytes32) {
            return bytes32("BRONZE");
        }
}

File 12 of 12 : ABDKMathQuad.sol
// SPDX-License-Identifier: BSD-4-Clause
/*
 * ABDK Math Quad Smart Contract Library.  Copyright © 2019 by ABDK Consulting.
 * Author: Mikhail Vladimirov <[email protected]>
 */
pragma solidity ^0.5.0 || ^0.6.0 || ^0.7.0;

/**
 * Smart contract library of mathematical functions operating with IEEE 754
 * quadruple-precision binary floating-point numbers (quadruple precision
 * numbers).  As long as quadruple precision numbers are 16-bytes long, they are
 * represented by bytes16 type.
 */
library ABDKMathQuad {
  /*
   * 0.
   */
  bytes16 private constant POSITIVE_ZERO = 0x00000000000000000000000000000000;

  /*
   * -0.
   */
  bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000;

  /*
   * +Infinity.
   */
  bytes16 private constant POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000;

  /*
   * -Infinity.
   */
  bytes16 private constant NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000;

  /*
   * Canonical NaN value.
   */
  bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;

  /**
   * Convert signed 256-bit integer number into quadruple precision number.
   *
   * @param x signed 256-bit integer number
   * @return quadruple precision number
   */
  function fromInt (int256 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      // We rely on overflow behavior here
      uint256 result = uint256 (x > 0 ? x : -x);

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112;
      if (x < 0) result |= 0x80000000000000000000000000000000;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into signed 256-bit integer number
   * rounding towards zero.  Revert on overflow.
   *
   * @param x quadruple precision number
   * @return signed 256-bit integer number
   */
  function toInt (bytes16 x) internal pure returns (int256) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    require (exponent <= 16638); // Overflow
    if (exponent < 16383) return 0; // Underflow

    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16495) result >>= 16495 - exponent;
    else if (exponent > 16495) result <<= exponent - 16495;

    if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative
      require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000);
      return -int256 (result); // We rely on overflow behavior here
    } else {
      require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int256 (result);
    }
  }

  /**
   * Convert unsigned 256-bit integer number into quadruple precision number.
   *
   * @param x unsigned 256-bit integer number
   * @return quadruple precision number
   */
  function fromUInt (uint256 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      uint256 result = x;

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into unsigned 256-bit integer number
   * rounding towards zero.  Revert on underflow.  Note, that negative floating
   * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer
   * without error, because they are rounded to zero.
   *
   * @param x quadruple precision number
   * @return unsigned 256-bit integer number
   */
  function toUInt (bytes16 x) internal pure returns (uint256) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    if (exponent < 16383) return 0; // Underflow

    require (uint128 (x) < 0x80000000000000000000000000000000); // Negative

    require (exponent <= 16638); // Overflow
    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16495) result >>= 16495 - exponent;
    else if (exponent > 16495) result <<= exponent - 16495;

    return result;
  }

  /**
   * Convert signed 128.128 bit fixed point number into quadruple precision
   * number.
   *
   * @param x signed 128.128 bit fixed point number
   * @return quadruple precision number
   */
  function from128x128 (int256 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      // We rely on overflow behavior here
      uint256 result = uint256 (x > 0 ? x : -x);

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16255 + msb << 112;
      if (x < 0) result |= 0x80000000000000000000000000000000;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into signed 128.128 bit fixed point
   * number.  Revert on overflow.
   *
   * @param x quadruple precision number
   * @return signed 128.128 bit fixed point number
   */
  function to128x128 (bytes16 x) internal pure returns (int256) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    require (exponent <= 16510); // Overflow
    if (exponent < 16255) return 0; // Underflow

    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16367) result >>= 16367 - exponent;
    else if (exponent > 16367) result <<= exponent - 16367;

    if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative
      require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000);
      return -int256 (result); // We rely on overflow behavior here
    } else {
      require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int256 (result);
    }
  }

  /**
   * Convert signed 64.64 bit fixed point number into quadruple precision
   * number.
   *
   * @param x signed 64.64 bit fixed point number
   * @return quadruple precision number
   */
  function from64x64 (int128 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      // We rely on overflow behavior here
      uint256 result = uint128 (x > 0 ? x : -x);

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16319 + msb << 112;
      if (x < 0) result |= 0x80000000000000000000000000000000;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into signed 64.64 bit fixed point
   * number.  Revert on overflow.
   *
   * @param x quadruple precision number
   * @return signed 64.64 bit fixed point number
   */
  function to64x64 (bytes16 x) internal pure returns (int128) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    require (exponent <= 16446); // Overflow
    if (exponent < 16319) return 0; // Underflow

    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16431) result >>= 16431 - exponent;
    else if (exponent > 16431) result <<= exponent - 16431;

    if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative
      require (result <= 0x80000000000000000000000000000000);
      return -int128 (result); // We rely on overflow behavior here
    } else {
      require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (result);
    }
  }

  /**
   * Convert octuple precision number into quadruple precision number.
   *
   * @param x octuple precision number
   * @return quadruple precision number
   */
  function fromOctuple (bytes32 x) internal pure returns (bytes16) {
    bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0;

    uint256 exponent = uint256 (x) >> 236 & 0x7FFFF;
    uint256 significand = uint256 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (exponent == 0x7FFFF) {
      if (significand > 0) return NaN;
      else return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
    }

    if (exponent > 278526)
      return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
    else if (exponent < 245649)
      return negative ? NEGATIVE_ZERO : POSITIVE_ZERO;
    else if (exponent < 245761) {
      significand = (significand | 0x100000000000000000000000000000000000000000000000000000000000) >> 245885 - exponent;
      exponent = 0;
    } else {
      significand >>= 124;
      exponent -= 245760;
    }

    uint128 result = uint128 (significand | exponent << 112);
    if (negative) result |= 0x80000000000000000000000000000000;

    return bytes16 (result);
  }

  /**
   * Convert quadruple precision number into octuple precision number.
   *
   * @param x quadruple precision number
   * @return octuple precision number
   */
  function toOctuple (bytes16 x) internal pure returns (bytes32) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    uint256 result = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (exponent == 0x7FFF) exponent = 0x7FFFF; // Infinity or NaN
    else if (exponent == 0) {
      if (result > 0) {
        uint256 msb = msb (result);
        result = result << 236 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        exponent = 245649 + msb;
      }
    } else {
      result <<= 124;
      exponent += 245760;
    }

    result |= exponent << 236;
    if (uint128 (x) >= 0x80000000000000000000000000000000)
      result |= 0x8000000000000000000000000000000000000000000000000000000000000000;

    return bytes32 (result);
  }

  /**
   * Convert double precision number into quadruple precision number.
   *
   * @param x double precision number
   * @return quadruple precision number
   */
  function fromDouble (bytes8 x) internal pure returns (bytes16) {
    uint256 exponent = uint64 (x) >> 52 & 0x7FF;

    uint256 result = uint64 (x) & 0xFFFFFFFFFFFFF;

    if (exponent == 0x7FF) exponent = 0x7FFF; // Infinity or NaN
    else if (exponent == 0) {
      if (result > 0) {
        uint256 msb = msb (result);
        result = result << 112 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        exponent = 15309 + msb;
      }
    } else {
      result <<= 60;
      exponent += 15360;
    }

    result |= exponent << 112;
    if (x & 0x8000000000000000 > 0)
      result |= 0x80000000000000000000000000000000;

    return bytes16 (uint128 (result));
  }

  /**
   * Convert quadruple precision number into double precision number.
   *
   * @param x quadruple precision number
   * @return double precision number
   */
  function toDouble (bytes16 x) internal pure returns (bytes8) {
    bool negative = uint128 (x) >= 0x80000000000000000000000000000000;

    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 significand = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (exponent == 0x7FFF) {
      if (significand > 0) return 0x7FF8000000000000; // NaN
      else return negative ?
          bytes8 (0xFFF0000000000000) : // -Infinity
          bytes8 (0x7FF0000000000000); // Infinity
    }

    if (exponent > 17406)
      return negative ?
          bytes8 (0xFFF0000000000000) : // -Infinity
          bytes8 (0x7FF0000000000000); // Infinity
    else if (exponent < 15309)
      return negative ?
          bytes8 (0x8000000000000000) : // -0
          bytes8 (0x0000000000000000); // 0
    else if (exponent < 15361) {
      significand = (significand | 0x10000000000000000000000000000) >> 15421 - exponent;
      exponent = 0;
    } else {
      significand >>= 60;
      exponent -= 15360;
    }

    uint64 result = uint64 (significand | exponent << 52);
    if (negative) result |= 0x8000000000000000;

    return bytes8 (result);
  }

  /**
   * Test whether given quadruple precision number is NaN.
   *
   * @param x quadruple precision number
   * @return true if x is NaN, false otherwise
   */
  function isNaN (bytes16 x) internal pure returns (bool) {
    return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >
      0x7FFF0000000000000000000000000000;
  }

  /**
   * Test whether given quadruple precision number is positive or negative
   * infinity.
   *
   * @param x quadruple precision number
   * @return true if x is positive or negative infinity, false otherwise
   */
  function isInfinity (bytes16 x) internal pure returns (bool) {
    return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==
      0x7FFF0000000000000000000000000000;
  }

  /**
   * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x
   * is positive.  Note that sign (-0) is zero.  Revert if x is NaN. 
   *
   * @param x quadruple precision number
   * @return sign of x
   */
  function sign (bytes16 x) internal pure returns (int8) {
    uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN

    if (absoluteX == 0) return 0;
    else if (uint128 (x) >= 0x80000000000000000000000000000000) return -1;
    else return 1;
  }

  /**
   * Calculate sign (x - y).  Revert if either argument is NaN, or both
   * arguments are infinities of the same sign. 
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return sign (x - y)
   */
  function cmp (bytes16 x, bytes16 y) internal pure returns (int8) {
    uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN

    uint128 absoluteY = uint128 (y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    require (absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN

    // Not infinities of the same sign
    require (x != y || absoluteX < 0x7FFF0000000000000000000000000000);

    if (x == y) return 0;
    else {
      bool negativeX = uint128 (x) >= 0x80000000000000000000000000000000;
      bool negativeY = uint128 (y) >= 0x80000000000000000000000000000000;

      if (negativeX) {
        if (negativeY) return absoluteX > absoluteY ? -1 : int8 (1);
        else return -1; 
      } else {
        if (negativeY) return 1;
        else return absoluteX > absoluteY ? int8 (1) : -1;
      }
    }
  }

  /**
   * Test whether x equals y.  NaN, infinity, and -infinity are not equal to
   * anything. 
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return true if x equals to y, false otherwise
   */
  function eq (bytes16 x, bytes16 y) internal pure returns (bool) {
    if (x == y) {
      return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <
        0x7FFF0000000000000000000000000000;
    } else return false;
  }

  /**
   * Calculate x + y.  Special values behave in the following way:
   *
   * NaN + x = NaN for any x.
   * Infinity + x = Infinity for any finite x.
   * -Infinity + x = -Infinity for any finite x.
   * Infinity + Infinity = Infinity.
   * -Infinity + -Infinity = -Infinity.
   * Infinity + -Infinity = -Infinity + Infinity = NaN.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function add (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;

    if (xExponent == 0x7FFF) {
      if (yExponent == 0x7FFF) { 
        if (x == y) return x;
        else return NaN;
      } else return x; 
    } else if (yExponent == 0x7FFF) return y;
    else {
      bool xSign = uint128 (x) >= 0x80000000000000000000000000000000;
      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xExponent == 0) xExponent = 1;
      else xSignifier |= 0x10000000000000000000000000000;

      bool ySign = uint128 (y) >= 0x80000000000000000000000000000000;
      uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (yExponent == 0) yExponent = 1;
      else ySignifier |= 0x10000000000000000000000000000;

      if (xSignifier == 0) return y == NEGATIVE_ZERO ? POSITIVE_ZERO : y;
      else if (ySignifier == 0) return x == NEGATIVE_ZERO ? POSITIVE_ZERO : x;
      else {
        int256 delta = int256 (xExponent) - int256 (yExponent);
  
        if (xSign == ySign) {
          if (delta > 112) return x;
          else if (delta > 0) ySignifier >>= uint256 (delta);
          else if (delta < -112) return y;
          else if (delta < 0) {
            xSignifier >>= uint256 (-delta);
            xExponent = yExponent;
          }
  
          xSignifier += ySignifier;
  
          if (xSignifier >= 0x20000000000000000000000000000) {
            xSignifier >>= 1;
            xExponent += 1;
          }
  
          if (xExponent == 0x7FFF)
            return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
          else {
            if (xSignifier < 0x10000000000000000000000000000) xExponent = 0;
            else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
  
            return bytes16 (uint128 (
                (xSign ? 0x80000000000000000000000000000000 : 0) |
                (xExponent << 112) |
                xSignifier)); 
          }
        } else {
          if (delta > 0) {
            xSignifier <<= 1;
            xExponent -= 1;
          } else if (delta < 0) {
            ySignifier <<= 1;
            xExponent = yExponent - 1;
          }

          if (delta > 112) ySignifier = 1;
          else if (delta > 1) ySignifier = (ySignifier - 1 >> uint256 (delta - 1)) + 1;
          else if (delta < -112) xSignifier = 1;
          else if (delta < -1) xSignifier = (xSignifier - 1 >> uint256 (-delta - 1)) + 1;

          if (xSignifier >= ySignifier) xSignifier -= ySignifier;
          else {
            xSignifier = ySignifier - xSignifier;
            xSign = ySign;
          }

          if (xSignifier == 0)
            return POSITIVE_ZERO;

          uint256 msb = msb (xSignifier);

          if (msb == 113) {
            xSignifier = xSignifier >> 1 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            xExponent += 1;
          } else if (msb < 112) {
            uint256 shift = 112 - msb;
            if (xExponent > shift) {
              xSignifier = xSignifier << shift & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
              xExponent -= shift;
            } else {
              xSignifier <<= xExponent - 1;
              xExponent = 0;
            }
          } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

          if (xExponent == 0x7FFF)
            return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
          else return bytes16 (uint128 (
              (xSign ? 0x80000000000000000000000000000000 : 0) |
              (xExponent << 112) |
              xSignifier));
        }
      }
    }
  }

  /**
   * Calculate x - y.  Special values behave in the following way:
   *
   * NaN - x = NaN for any x.
   * Infinity - x = Infinity for any finite x.
   * -Infinity - x = -Infinity for any finite x.
   * Infinity - -Infinity = Infinity.
   * -Infinity - Infinity = -Infinity.
   * Infinity - Infinity = -Infinity - -Infinity = NaN.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function sub (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    return add (x, y ^ 0x80000000000000000000000000000000);
  }

  /**
   * Calculate x * y.  Special values behave in the following way:
   *
   * NaN * x = NaN for any x.
   * Infinity * x = Infinity for any finite positive x.
   * Infinity * x = -Infinity for any finite negative x.
   * -Infinity * x = -Infinity for any finite positive x.
   * -Infinity * x = Infinity for any finite negative x.
   * Infinity * 0 = NaN.
   * -Infinity * 0 = NaN.
   * Infinity * Infinity = Infinity.
   * Infinity * -Infinity = -Infinity.
   * -Infinity * Infinity = -Infinity.
   * -Infinity * -Infinity = Infinity.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function mul (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;

    if (xExponent == 0x7FFF) {
      if (yExponent == 0x7FFF) {
        if (x == y) return x ^ y & 0x80000000000000000000000000000000;
        else if (x ^ y == 0x80000000000000000000000000000000) return x | y;
        else return NaN;
      } else {
        if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
        else return x ^ y & 0x80000000000000000000000000000000;
      }
    } else if (yExponent == 0x7FFF) {
        if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
        else return y ^ x & 0x80000000000000000000000000000000;
    } else {
      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xExponent == 0) xExponent = 1;
      else xSignifier |= 0x10000000000000000000000000000;

      uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (yExponent == 0) yExponent = 1;
      else ySignifier |= 0x10000000000000000000000000000;

      xSignifier *= ySignifier;
      if (xSignifier == 0)
        return (x ^ y) & 0x80000000000000000000000000000000 > 0 ?
            NEGATIVE_ZERO : POSITIVE_ZERO;

      xExponent += yExponent;

      uint256 msb =
        xSignifier >= 0x200000000000000000000000000000000000000000000000000000000 ? 225 :
        xSignifier >= 0x100000000000000000000000000000000000000000000000000000000 ? 224 :
        msb (xSignifier);

      if (xExponent + msb < 16496) { // Underflow
        xExponent = 0;
        xSignifier = 0;
      } else if (xExponent + msb < 16608) { // Subnormal
        if (xExponent < 16496)
          xSignifier >>= 16496 - xExponent;
        else if (xExponent > 16496)
          xSignifier <<= xExponent - 16496;
        xExponent = 0;
      } else if (xExponent + msb > 49373) {
        xExponent = 0x7FFF;
        xSignifier = 0;
      } else {
        if (msb > 112)
          xSignifier >>= msb - 112;
        else if (msb < 112)
          xSignifier <<= 112 - msb;

        xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

        xExponent = xExponent + msb - 16607;
      }

      return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) |
          xExponent << 112 | xSignifier));
    }
  }

  /**
   * Calculate x / y.  Special values behave in the following way:
   *
   * NaN / x = NaN for any x.
   * x / NaN = NaN for any x.
   * Infinity / x = Infinity for any finite non-negative x.
   * Infinity / x = -Infinity for any finite negative x including -0.
   * -Infinity / x = -Infinity for any finite non-negative x.
   * -Infinity / x = Infinity for any finite negative x including -0.
   * x / Infinity = 0 for any finite non-negative x.
   * x / -Infinity = -0 for any finite non-negative x.
   * x / Infinity = -0 for any finite non-negative x including -0.
   * x / -Infinity = 0 for any finite non-negative x including -0.
   * 
   * Infinity / Infinity = NaN.
   * Infinity / -Infinity = -NaN.
   * -Infinity / Infinity = -NaN.
   * -Infinity / -Infinity = NaN.
   *
   * Division by zero behaves in the following way:
   *
   * x / 0 = Infinity for any finite positive x.
   * x / -0 = -Infinity for any finite positive x.
   * x / 0 = -Infinity for any finite negative x.
   * x / -0 = Infinity for any finite negative x.
   * 0 / 0 = NaN.
   * 0 / -0 = NaN.
   * -0 / 0 = NaN.
   * -0 / -0 = NaN.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function div (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;

    if (xExponent == 0x7FFF) {
      if (yExponent == 0x7FFF) return NaN;
      else return x ^ y & 0x80000000000000000000000000000000;
    } else if (yExponent == 0x7FFF) {
      if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;
      else return POSITIVE_ZERO | (x ^ y) & 0x80000000000000000000000000000000;
    } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {
      if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
      else return POSITIVE_INFINITY | (x ^ y) & 0x80000000000000000000000000000000;
    } else {
      uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (yExponent == 0) yExponent = 1;
      else ySignifier |= 0x10000000000000000000000000000;

      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xExponent == 0) {
        if (xSignifier != 0) {
          uint shift = 226 - msb (xSignifier);

          xSignifier <<= shift;

          xExponent = 1;
          yExponent += shift - 114;
        }
      }
      else {
        xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114;
      }

      xSignifier = xSignifier / ySignifier;
      if (xSignifier == 0)
        return (x ^ y) & 0x80000000000000000000000000000000 > 0 ?
            NEGATIVE_ZERO : POSITIVE_ZERO;

      assert (xSignifier >= 0x1000000000000000000000000000);

      uint256 msb =
        xSignifier >= 0x80000000000000000000000000000 ? msb (xSignifier) :
        xSignifier >= 0x40000000000000000000000000000 ? 114 :
        xSignifier >= 0x20000000000000000000000000000 ? 113 : 112;

      if (xExponent + msb > yExponent + 16497) { // Overflow
        xExponent = 0x7FFF;
        xSignifier = 0;
      } else if (xExponent + msb + 16380  < yExponent) { // Underflow
        xExponent = 0;
        xSignifier = 0;
      } else if (xExponent + msb + 16268  < yExponent) { // Subnormal
        if (xExponent + 16380 > yExponent)
          xSignifier <<= xExponent + 16380 - yExponent;
        else if (xExponent + 16380 < yExponent)
          xSignifier >>= yExponent - xExponent - 16380;

        xExponent = 0;
      } else { // Normal
        if (msb > 112)
          xSignifier >>= msb - 112;

        xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

        xExponent = xExponent + msb + 16269 - yExponent;
      }

      return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) |
          xExponent << 112 | xSignifier));
    }
  }

  /**
   * Calculate -x.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function neg (bytes16 x) internal pure returns (bytes16) {
    return x ^ 0x80000000000000000000000000000000;
  }

  /**
   * Calculate |x|.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function abs (bytes16 x) internal pure returns (bytes16) {
    return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
  }

  /**
   * Calculate square root of x.  Return NaN on negative x excluding -0.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function sqrt (bytes16 x) internal pure returns (bytes16) {
    if (uint128 (x) >  0x80000000000000000000000000000000) return NaN;
    else {
      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
      if (xExponent == 0x7FFF) return x;
      else {
        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        if (xExponent == 0) xExponent = 1;
        else xSignifier |= 0x10000000000000000000000000000;

        if (xSignifier == 0) return POSITIVE_ZERO;

        bool oddExponent = xExponent & 0x1 == 0;
        xExponent = xExponent + 16383 >> 1;

        if (oddExponent) {
          if (xSignifier >= 0x10000000000000000000000000000)
            xSignifier <<= 113;
          else {
            uint256 msb = msb (xSignifier);
            uint256 shift = (226 - msb) & 0xFE;
            xSignifier <<= shift;
            xExponent -= shift - 112 >> 1;
          }
        } else {
          if (xSignifier >= 0x10000000000000000000000000000)
            xSignifier <<= 112;
          else {
            uint256 msb = msb (xSignifier);
            uint256 shift = (225 - msb) & 0xFE;
            xSignifier <<= shift;
            xExponent -= shift - 112 >> 1;
          }
        }

        uint256 r = 0x10000000000000000000000000000;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1; // Seven iterations should be enough
        uint256 r1 = xSignifier / r;
        if (r1 < r) r = r1;

        return bytes16 (uint128 (xExponent << 112 | r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
      }
    }
  }

  /**
   * Calculate binary logarithm of x.  Return NaN on negative x excluding -0.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function log_2 (bytes16 x) internal pure returns (bytes16) {
    if (uint128 (x) > 0x80000000000000000000000000000000) return NaN;
    else if (x == 0x3FFF0000000000000000000000000000) return POSITIVE_ZERO; 
    else {
      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
      if (xExponent == 0x7FFF) return x;
      else {
        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        if (xExponent == 0) xExponent = 1;
        else xSignifier |= 0x10000000000000000000000000000;

        if (xSignifier == 0) return NEGATIVE_INFINITY;

        bool resultNegative;
        uint256 resultExponent = 16495;
        uint256 resultSignifier;

        if (xExponent >= 0x3FFF) {
          resultNegative = false;
          resultSignifier = xExponent - 0x3FFF;
          xSignifier <<= 15;
        } else {
          resultNegative = true;
          if (xSignifier >= 0x10000000000000000000000000000) {
            resultSignifier = 0x3FFE - xExponent;
            xSignifier <<= 15;
          } else {
            uint256 msb = msb (xSignifier);
            resultSignifier = 16493 - msb;
            xSignifier <<= 127 - msb;
          }
        }

        if (xSignifier == 0x80000000000000000000000000000000) {
          if (resultNegative) resultSignifier += 1;
          uint256 shift = 112 - msb (resultSignifier);
          resultSignifier <<= shift;
          resultExponent -= shift;
        } else {
          uint256 bb = resultNegative ? 1 : 0;
          while (resultSignifier < 0x10000000000000000000000000000) {
            resultSignifier <<= 1;
            resultExponent -= 1;
  
            xSignifier *= xSignifier;
            uint256 b = xSignifier >> 255;
            resultSignifier += b ^ bb;
            xSignifier >>= 127 + b;
          }
        }

        return bytes16 (uint128 ((resultNegative ? 0x80000000000000000000000000000000 : 0) |
            resultExponent << 112 | resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
      }
    }
  }

  /**
   * Calculate natural logarithm of x.  Return NaN on negative x excluding -0.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function ln (bytes16 x) internal pure returns (bytes16) {
    return mul (log_2 (x), 0x3FFE62E42FEFA39EF35793C7673007E5);
  }

  /**
   * Calculate 2^x.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function pow_2 (bytes16 x) internal pure returns (bytes16) {
    bool xNegative = uint128 (x) > 0x80000000000000000000000000000000;
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (xExponent == 0x7FFF && xSignifier != 0) return NaN;
    else if (xExponent > 16397)
      return xNegative ? POSITIVE_ZERO : POSITIVE_INFINITY;
    else if (xExponent < 16255)
      return 0x3FFF0000000000000000000000000000;
    else {
      if (xExponent == 0) xExponent = 1;
      else xSignifier |= 0x10000000000000000000000000000;

      if (xExponent > 16367)
        xSignifier <<= xExponent - 16367;
      else if (xExponent < 16367)
        xSignifier >>= 16367 - xExponent;

      if (xNegative && xSignifier > 0x406E00000000000000000000000000000000)
        return POSITIVE_ZERO;

      if (!xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        return POSITIVE_INFINITY;

      uint256 resultExponent = xSignifier >> 128;
      xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xNegative && xSignifier != 0) {
        xSignifier = ~xSignifier;
        resultExponent += 1;
      }

      uint256 resultSignifier = 0x80000000000000000000000000000000;
      if (xSignifier & 0x80000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
      if (xSignifier & 0x40000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
      if (xSignifier & 0x20000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
      if (xSignifier & 0x10000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
      if (xSignifier & 0x8000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
      if (xSignifier & 0x4000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
      if (xSignifier & 0x2000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
      if (xSignifier & 0x1000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
      if (xSignifier & 0x800000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
      if (xSignifier & 0x400000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
      if (xSignifier & 0x200000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
      if (xSignifier & 0x100000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
      if (xSignifier & 0x80000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
      if (xSignifier & 0x40000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
      if (xSignifier & 0x20000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000162E525EE054754457D5995292026 >> 128;
      if (xSignifier & 0x10000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
      if (xSignifier & 0x8000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
      if (xSignifier & 0x4000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
      if (xSignifier & 0x2000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000162E43F4F831060E02D839A9D16D >> 128;
      if (xSignifier & 0x1000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
      if (xSignifier & 0x800000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
      if (xSignifier & 0x400000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
      if (xSignifier & 0x200000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
      if (xSignifier & 0x100000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
      if (xSignifier & 0x80000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
      if (xSignifier & 0x40000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
      if (xSignifier & 0x20000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
      if (xSignifier & 0x10000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
      if (xSignifier & 0x8000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
      if (xSignifier & 0x4000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
      if (xSignifier & 0x2000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
      if (xSignifier & 0x1000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
      if (xSignifier & 0x800000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
      if (xSignifier & 0x400000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
      if (xSignifier & 0x200000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000162E42FEFB2FED257559BDAA >> 128;
      if (xSignifier & 0x100000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
      if (xSignifier & 0x80000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
      if (xSignifier & 0x40000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
      if (xSignifier & 0x20000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
      if (xSignifier & 0x10000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000B17217F7D20CF927C8E94C >> 128;
      if (xSignifier & 0x8000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
      if (xSignifier & 0x4000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000002C5C85FDF477B662B26945 >> 128;
      if (xSignifier & 0x2000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000162E42FEFA3AE53369388C >> 128;
      if (xSignifier & 0x1000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000B17217F7D1D351A389D40 >> 128;
      if (xSignifier & 0x800000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
      if (xSignifier & 0x400000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
      if (xSignifier & 0x200000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000162E42FEFA39FE95583C2 >> 128;
      if (xSignifier & 0x100000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
      if (xSignifier & 0x80000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
      if (xSignifier & 0x40000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000002C5C85FDF473E242EA38 >> 128;
      if (xSignifier & 0x20000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000162E42FEFA39F02B772C >> 128;
      if (xSignifier & 0x10000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
      if (xSignifier & 0x8000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
      if (xSignifier & 0x4000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000002C5C85FDF473DEA871F >> 128;
      if (xSignifier & 0x2000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000162E42FEFA39EF44D91 >> 128;
      if (xSignifier & 0x1000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000B17217F7D1CF79E949 >> 128;
      if (xSignifier & 0x800000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
      if (xSignifier & 0x400000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
      if (xSignifier & 0x200000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000162E42FEFA39EF366F >> 128;
      if (xSignifier & 0x100000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000B17217F7D1CF79AFA >> 128;
      if (xSignifier & 0x80000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
      if (xSignifier & 0x40000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
      if (xSignifier & 0x20000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000162E42FEFA39EF358 >> 128;
      if (xSignifier & 0x10000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000B17217F7D1CF79AB >> 128;
      if (xSignifier & 0x8000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5 >> 128;
      if (xSignifier & 0x4000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000002C5C85FDF473DE6A >> 128;
      if (xSignifier & 0x2000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000162E42FEFA39EF34 >> 128;
      if (xSignifier & 0x1000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000B17217F7D1CF799 >> 128;
      if (xSignifier & 0x800000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000058B90BFBE8E7BCC >> 128;
      if (xSignifier & 0x400000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000002C5C85FDF473DE5 >> 128;
      if (xSignifier & 0x200000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000162E42FEFA39EF2 >> 128;
      if (xSignifier & 0x100000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000B17217F7D1CF78 >> 128;
      if (xSignifier & 0x80000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000058B90BFBE8E7BB >> 128;
      if (xSignifier & 0x40000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000002C5C85FDF473DD >> 128;
      if (xSignifier & 0x20000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000162E42FEFA39EE >> 128;
      if (xSignifier & 0x10000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000B17217F7D1CF6 >> 128;
      if (xSignifier & 0x8000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000058B90BFBE8E7A >> 128;
      if (xSignifier & 0x4000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000002C5C85FDF473C >> 128;
      if (xSignifier & 0x2000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000162E42FEFA39D >> 128;
      if (xSignifier & 0x1000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000B17217F7D1CE >> 128;
      if (xSignifier & 0x800000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000058B90BFBE8E6 >> 128;
      if (xSignifier & 0x400000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000002C5C85FDF472 >> 128;
      if (xSignifier & 0x200000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000162E42FEFA38 >> 128;
      if (xSignifier & 0x100000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000B17217F7D1B >> 128;
      if (xSignifier & 0x80000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000058B90BFBE8D >> 128;
      if (xSignifier & 0x40000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000002C5C85FDF46 >> 128;
      if (xSignifier & 0x20000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000162E42FEFA2 >> 128;
      if (xSignifier & 0x10000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000B17217F7D0 >> 128;
      if (xSignifier & 0x8000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000058B90BFBE7 >> 128;
      if (xSignifier & 0x4000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000002C5C85FDF3 >> 128;
      if (xSignifier & 0x2000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000162E42FEF9 >> 128;
      if (xSignifier & 0x1000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000B17217F7C >> 128;
      if (xSignifier & 0x800000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000058B90BFBD >> 128;
      if (xSignifier & 0x400000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000002C5C85FDE >> 128;
      if (xSignifier & 0x200000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000162E42FEE >> 128;
      if (xSignifier & 0x100000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000B17217F6 >> 128;
      if (xSignifier & 0x80000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000058B90BFA >> 128;
      if (xSignifier & 0x40000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000002C5C85FC >> 128;
      if (xSignifier & 0x20000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000162E42FD >> 128;
      if (xSignifier & 0x10000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000B17217E >> 128;
      if (xSignifier & 0x8000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000058B90BE >> 128;
      if (xSignifier & 0x4000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000002C5C85E >> 128;
      if (xSignifier & 0x2000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000162E42E >> 128;
      if (xSignifier & 0x1000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000B17216 >> 128;
      if (xSignifier & 0x800000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000058B90A >> 128;
      if (xSignifier & 0x400000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000002C5C84 >> 128;
      if (xSignifier & 0x200000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000162E41 >> 128;
      if (xSignifier & 0x100000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000B1720 >> 128;
      if (xSignifier & 0x80000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000058B8F >> 128;
      if (xSignifier & 0x40000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000002C5C7 >> 128;
      if (xSignifier & 0x20000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000162E3 >> 128;
      if (xSignifier & 0x10000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000B171 >> 128;
      if (xSignifier & 0x8000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000058B8 >> 128;
      if (xSignifier & 0x4000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000002C5B >> 128;
      if (xSignifier & 0x2000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000162D >> 128;
      if (xSignifier & 0x1000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000B16 >> 128;
      if (xSignifier & 0x800 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000058A >> 128;
      if (xSignifier & 0x400 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000002C4 >> 128;
      if (xSignifier & 0x200 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000161 >> 128;
      if (xSignifier & 0x100 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000000B0 >> 128;
      if (xSignifier & 0x80 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000057 >> 128;
      if (xSignifier & 0x40 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000002B >> 128;
      if (xSignifier & 0x20 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000015 >> 128;
      if (xSignifier & 0x10 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000000A >> 128;
      if (xSignifier & 0x8 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000004 >> 128;
      if (xSignifier & 0x4 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000001 >> 128;

      if (!xNegative) {
        resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        resultExponent += 0x3FFF;
      } else if (resultExponent <= 0x3FFE) {
        resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        resultExponent = 0x3FFF - resultExponent;
      } else {
        resultSignifier = resultSignifier >> resultExponent - 16367;
        resultExponent = 0;
      }

      return bytes16 (uint128 (resultExponent << 112 | resultSignifier));
    }
  }

  /**
   * Calculate e^x.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function exp (bytes16 x) internal pure returns (bytes16) {
    return pow_2 (mul (x, 0x3FFF71547652B82FE1777D0FFDA0D23A));
  }

  /**
   * Get index of the most significant non-zero bit in binary representation of
   * x.  Reverts if x is zero.
   *
   * @return index of the most significant non-zero bit in binary representation
   *         of x
   */
  function msb (uint256 x) private pure returns (uint256) {
    require (x > 0);

    uint256 result = 0;

    if (x >= 0x100000000000000000000000000000000) { x >>= 128; result += 128; }
    if (x >= 0x10000000000000000) { x >>= 64; result += 64; }
    if (x >= 0x100000000) { x >>= 32; result += 32; }
    if (x >= 0x10000) { x >>= 16; result += 16; }
    if (x >= 0x100) { x >>= 8; result += 8; }
    if (x >= 0x10) { x >>= 4; result += 4; }
    if (x >= 0x4) { x >>= 2; result += 2; }
    if (x >= 0x2) result += 1; // No need to shift x anymore

    return result;
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_IN_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OUT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_POW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NEGATIVE_INFINITY","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getColor","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"iBONE","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRepricer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"int256","name":"x","type":"int256"}],"name":"ln","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"int256","name":"x","type":"int256"}],"name":"ncdf","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"pMin","type":"uint256"},{"internalType":"int256","name":"volatility","type":"int256"},{"internalType":"contract IVault","name":"_vault","type":"address"},{"internalType":"uint256[2]","name":"primary","type":"uint256[2]"},{"internalType":"uint256[2]","name":"complement","type":"uint256[2]"},{"internalType":"int256","name":"_liveUnderlingValue","type":"int256"}],"name":"reprice","outputs":[{"internalType":"uint256","name":"newPrimaryLeverage","type":"uint256"},{"internalType":"uint256","name":"newComplementLeverage","type":"uint256"},{"internalType":"int256","name":"estPricePrimary","type":"int256"},{"internalType":"int256","name":"estPriceComplement","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"x","type":"int256"}],"name":"sqrt","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]

608060405234801561001057600080fd5b506141fb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638e6f235311610097578063a598cef811610066578063a598cef8146102d3578063c36596a6146101f4578063dd43eb57146102f0578063ec093021146102f8576100f5565b80638e6f23531461022957806395d89b4114610246578063992e2a92146102c35780639a86139b146102cb576100f5565b806340179d83116100d357806340179d83146101f45780634dcd7dee146101fc578063665df4601461020457806373d1747b14610221576100f5565b806301032adc146100fa5780631a1afbc5146101145780631f072062146101d8575b600080fd5b610102610300565b60408051918252519081900360200190f35b6101b2600480360361010081101561012b57600080fd5b60408051808201825283359360208101359373ffffffffffffffffffffffffffffffffffffffff8483013516939082019260a0830191606084019060029083908390808284376000920191909152505060408051808201825292959493818101939250906002908390839080828437600092019190915250919450509035915061030c9050565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6101e06104b4565b604080519115158252519081900360200190f35b6101026104b9565b6101026104c5565b6101026004803603602081101561021a57600080fd5b50356104e9565b61010261051e565b6101026004803603602081101561023f57600080fd5b5035610532565b61024e610551565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610288578181015183820152602001610270565b50505050905090810190601f1680156102b55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610102610588565b610102610594565b610102600480360360208110156102e957600080fd5b50356105b8565b610102610743565b610102610748565b671bc16d674ec7ffff81565b600080808073ffffffffffffffffffffffffffffffffffffffff881661039357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a65726f206f7261636c65000000000000000000000000000000000000000000604482015290519081900360640190fd5b61043261039f89610758565b6103b1876103ac8c61098d565b610b23565b61042b8b73ffffffffffffffffffffffffffffffffffffffff166366101b646040518163ffffffff1660e01b815260040160206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d602081101561042457600080fd5b5051610b54565b8d8d610b6f565b9092509050600082670de0b6b3a764000083028161044c57fe5b059050600061046989600160200201518960016020020151610bb6565b905061049761049261048b836104868c6000602002015187610bb6565b610bb6565b8b51610cca565b6104e9565b95506104a38187610cca565b945050509650965096509692505050565b600190565b670de0b6b3a764000081565b7f800000000000000000000000000000000000000000000000000000000000000081565b600061051661050861050384670de0b6b3a7640000610e49565b610e67565b670de0b6b3a76400006110b1565b90505b919050565b6402540be400670de0b6b3a76400005b0481565b600061051661050861054c84670de0b6b3a7640000610e49565b6110cd565b60408051808201909152600a81527f7835526570726963657200000000000000000000000000000000000000000000602082015290565b6704a03ce68d21555681565b7f42524f4e5a45000000000000000000000000000000000000000000000000000090565b6000806105cd83670de0b6b3a7640000610e49565b905060006105da82611101565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106128361060d6025611126565b611192565b60000b148061062f575061062f8261062a6025611126565b611391565b156106c957600061066261065d61064e610648866113f7565b8661141c565b6106586002611126565b611860565b611c6d565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106a08461060d6602831c2082c9f3655af3107a4000610e49565b60000b14156106ba576106b38382611ca1565b91506106c7565b6106c48382611e43565b91505b505b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106f384611ed4565b60000b14806107085750610708836000611391565b6107245761071f6107196001611126565b82611f79565b610726565b805b905061073a81670de0b6b3a76400006110b1565b95945050505050565b600181565b6002670de0b6b3a764000061052e565b60008173ffffffffffffffffffffffffffffffffffffffff1663dbcb32bf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156107a057600080fd5b505afa1580156107b4573d6000803e3d6000fd5b505050506040513d60208110156107ca57600080fd5b5051604080517fab56c592000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163ab56c59291600480820192602092909190829003018186803b15801561083457600080fd5b505afa158015610848573d6000803e3d6000fd5b505050506040513d602081101561085e57600080fd5b5051604080517fdbcb32bf000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff85169163dbcb32bf916004808301926020929190829003018186803b1580156108c657600080fd5b505afa1580156108da573d6000803e3d6000fd5b505050506040513d60208110156108f057600080fd5b5051604080517fc6bb30e2000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163c6bb30e291600480820192602092909190829003018186803b15801561095a57600080fd5b505afa15801561096e573d6000803e3d6000fd5b505050506040513d602081101561098457600080fd5b50510192915050565b6000808273ffffffffffffffffffffffffffffffffffffffff16635b69a7d860006040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156109e257600080fd5b505afa1580156109f6573d6000803e3d6000fd5b505050506040513d6020811015610a0c57600080fd5b5051604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163feaf968c9160048082019260a092909190829003018186803b158015610a7657600080fd5b505afa158015610a8a573d6000803e3d6000fd5b505050506040513d60a0811015610aa057600080fd5b506020810151606090910151909250905080610b1d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f454d5054595f4f5241434c455f4c41544553545f524f554e4400000000000000604482015290519081900360640190fd5b50919050565b600082670de0b6b3a76400008484030281610b3a57fe5b05600502670de0b6b3a76400006005020190505b92915050565b60006301e13380428303670de0b6b3a7640000020592915050565b600080610b7d868685611fa7565b915083821215610b8b578391505b670de0b6b3a76400008702848103831315610ba65784810392505b8281039150509550959350505050565b6000828202831580610bd0575082848281610bcd57fe5b04145b610c3b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b6706f05b59d3b20000810181811015610cb557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a7640000815b0495945050505050565b600081610d3857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4449565f5a45524f000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a76400008302831580610d605750670de0b6b3a7640000848281610d5d57fe5b04145b610dcb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b60028304810181811015610e4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b838181610cc057fe5b6000610e60610e57846120b0565b61065884611126565b9392505050565b60006f80000000000000000000000000000000608083901c1115610eac57507f7fff800000000000000000000000000000000000000000000000000000000000610519565b617fff60f083901c811690811415610ec75782915050610519565b6dffffffffffffffffffffffffffff608084901c1681610eea5760019150610efc565b6e010000000000000000000000000000175b80610f0d5750600091506105199050565b613fff8201600190811c9216158015610f89576e0100000000000000000000000000008210610f4257607182901b9150610f84565b6000610f4d83612152565b60e20360fe167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810160011c909403939290921b91505b610fed565b6e0100000000000000000000000000008210610fab57607082901b9150610fed565b6000610fb683612152565b60e10360fe167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810160011c909403939290921b91505b6e01000000000000000000000000000080830401600190811c9081848161101057fe5b048201901c9050600181848161102257fe5b048201901c9050600181848161103457fe5b048201901c9050600181848161104657fe5b048201901c9050600181848161105857fe5b048201901c9050600181848161106a57fe5b048201901c9050600081848161107c57fe5b0490508181101561108b578091505b816dffffffffffffffffffffffffffff16607086901b1760801b95505050505050610519565b6000610e606110c8846110c385611126565b61141c565b612202565b60006105166110db83612325565b7f3ffe62e42fefa39ef35793c7673007e50000000000000000000000000000000061141c565b7f7fffffffffffffffffffffffffffffff000000000000000000000000000000001690565b60008161113557506000610519565b81600061114182612152565b9050607081101561115a578060700382901b915061116d565b607081111561116d576070810382901c91505b613fff0160701b6dffffffffffffffffffffffffffff919091161760801b9050610519565b60006f7fffffffffffffffffffffffffffffff608084901c166f7fff00000000000000000000000000008111156111c857600080fd5b6f7fffffffffffffffffffffffffffffff608084901c166f7fff00000000000000000000000000008111156111fc57600080fd5b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000085811690851614158061125157506f7fff0000000000000000000000000000826fffffffffffffffffffffffffffffffff16105b61125a57600080fd5b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000858116908516141561129257600092505050610b4e565b6f80000000000000000000000000000000608086811c82118015929187901c9190911015906113205780156112f357826fffffffffffffffffffffffffffffffff16846fffffffffffffffffffffffffffffffff16116112f3576001611315565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b945050505050610b4e565b8015611333576001945050505050610b4e565b826fffffffffffffffffffffffffffffffff16846fffffffffffffffffffffffffffffffff1611611384577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611315565b6001945050505050610b4e565b60007fffffffffffffffffffffffffffffffff0000000000000000000000000000000083811690831614156113ef57506f7fff00000000000000000000000000006f7fffffffffffffffffffffffffffffff608084901c1610610b4e565b506000610b4e565b7f80000000000000000000000000000000000000000000000000000000000000001890565b6000617fff60f084811c8216919084901c81169082141561159c5780617fff141561151d577fffffffffffffffffffffffffffffffff00000000000000000000000000000000858116908516141561149b575050507f800000000000000000000000000000000000000000000000000000000000000081168218610b4e565b7f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffff000000000000000000000000000000008686181614156114f257505050818117610b4e565b507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b7f7fffffffffffffffffffffffffffffff00000000000000000000000000000000841661156f57507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050507f800000000000000000000000000000000000000000000000000000000000000081168218610b4e565b80617fff1415611625577f7fffffffffffffffffffffffffffffff0000000000000000000000000000000085166115f857507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050507f800000000000000000000000000000000000000000000000000000000000000082168118610b4e565b6dffffffffffffffffffffffffffff608086901c1682611648576001925061165a565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608086901c168261167d576001925061168f565b6e010000000000000000000000000000175b90810290816116f4577f8000000000000000000000000000000000000000000000000000000000000000878718166116c8576000611315565b7f8000000000000000000000000000000000000000000000000000000000000000945050505050610b4e565b9282019260007c020000000000000000000000000000000000000000000000000000000083101561175a577c01000000000000000000000000000000000000000000000000000000008310156117525761174d83612152565b611755565b60e05b61175d565b60e15b9050614070818601101561177857600094506000925061181c565b6140e081860110156117bb5761407085101561179d57846140700383901c92506117b2565b6140708511156117b257614070850383901b92505b6000945061181c565b61c0dd81860111156117d557617fff94506000925061181c565b60708111156117ec576070810383901c92506117ff565b60708110156117ff578060700383901b92505b6dffffffffffffffffffffffffffff831692506140df8186010394505b82607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610b4e565b6000617fff60f084811c8216919084901c8116908214156118b05780617fff141561156f57507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b80617fff1415611938577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561190b57507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050508082187f800000000000000000000000000000000000000000000000000000000000000016610b4e565b7f7fffffffffffffffffffffffffffffff000000000000000000000000000000008416611a00577f7fffffffffffffffffffffffffffffff0000000000000000000000000000000085166119b157507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050508082187f8000000000000000000000000000000000000000000000000000000000000000167f7fff00000000000000000000000000000000000000000000000000000000000017610b4e565b6dffffffffffffffffffffffffffff608085901c1681611a235760019150611a35565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608087901c1683611a99578015611a94576000611a6082612152565b6001955060e2039384017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e01939190911b90505b611aae565b6e0100000000000000000000000000001760721b5b818181611ab757fe5b04905080611aef577f8000000000000000000000000000000000000000000000000000000000000000878718166116c8576000611315565b6d1000000000000000000000000000811015611b0757fe5b60006e080000000000000000000000000000821015611b68576e040000000000000000000000000000821015611b5d576e020000000000000000000000000000821015611b55576070611b58565b60715b611b60565b60725b60ff16611b71565b611b7182612152565b905083614071018186011115611b8f57617fff945060009150611c29565b83818601613ffc011015611baa576000945060009150611c29565b83818601613f8c011015611bf7578385613ffc011115611bd5578385613ffc010382901b9150611bee565b8385613ffc011015611bee57613ffc8585030382901c91505b60009450611c29565b6070811115611c0a576070810382901c91505b6dffffffffffffffffffffffffffff8216915083818601613f8d010394505b81607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610b4e565b6000610516611c9c837f3fff71547652b82fe1777d0ffda0d23a0000000000000000000000000000000061141c565b6125d7565b600080611d5c611d46611d30611d1a611d04611cec611cce660140b5e5d6593f662386f26fc10000610e49565b8a611ce766027cfea3c34b2866038d7ea4c68000610e49565b613bea565b89611ce7660243b55f4b9a8d655af3107a4000610e49565b88611ce7651ed7f455feaf64e8d4a51000610e49565b87611ce76565ef7e5b3d8f64e8d4a51000610e49565b86611ce765c9314dd1b6cb64e8d4a51000610e49565b85611ce765c846e82396b864e8d4a51000610e49565b90506000611e2e611e17611e00611de9611dd2611dba611da4611d8d660323e328a37c70662386f26fc10000610e49565b8c611ce7659fad4fc2b238655af3107a4000610e49565b8b611ce7650e9c3b9924c764e8d4a51000610e49565b8a611ce7660315442329bd956509184e72a000610e49565b89611ce766010db93eb39b9a64e8d4a51000610e49565b88611ce7660243a6ccd22a0f64e8d4a51000610e49565b87611ce76602d1fb234ac30c64e8d4a51000610e49565b86611ce76601908dd0472d7064e8d4a51000610e49565b905061073a611e3d858461141c565b82611860565b600080611e6384611e54600d611126565b611e5e6014611126565b613bff565b9050611e7984611e736004611126565b83613bff565b9050611e8984611e736003611126565b9050611e9984611e736002611126565b9050611ea984611e736001611126565b9050611ecc83610658611ec6643a5cab35c764174876e800610e49565b84611860565b949350505050565b60006f7fffffffffffffffffffffffffffffff608083901c166f7fff0000000000000000000000000000811115611f0a57600080fd5b6fffffffffffffffffffffffffffffffff8116611f2b576000915050610519565b6f80000000000000000000000000000000608084901c10611f6f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915050610519565b6001915050610519565b6000610e60837f80000000000000000000000000000000000000000000000000000000000000008418613c0f565b600080670de0b6b3a7640000611fbc856104e9565b840281611fc557fe5b0590506000816ec097ce7bc90715b34b9f100000000081611fe257fe5b0590506f01812f9cf7920e2b66973e20000000008480028602056000670de0b6b3a76400008261201560048b5b05610532565b0184028161201f57fe5b059050600061202f8583036105b8565b600402670de0b6b3a76400008a612045856105b8565b028161204d57fe5b05039050670de0b6b3a76400008361206660068c61200f565b0185028161207057fe5b05915060006120808684036105b8565b600602670de0b6b3a76400008b612096866105b8565b028161209e57fe5b05039091039998505050505050505050565b6000816120bf57506000610519565b60008083136120d157826000036120d3565b825b905060006120e082612152565b905060708110156120f9578060700382901b915061210c565b607081111561210c576070810382901c91505b6dffffffffffffffffffffffffffff909116613fff820160701b17906000841215612147576f80000000000000000000000000000000821791505b5060801b9050610519565b600080821161216057600080fd5b6000700100000000000000000000000000000000831061218257608092831c92015b68010000000000000000831061219a57604092831c92015b64010000000083106121ae57602092831c92015b6201000083106121c057601092831c92015b61010083106121d157600892831c92015b601083106121e157600492831c92015b600483106121f157600292831c92015b600283106105165760010192915050565b6000617fff60f083901c166140fe81111561221c57600080fd5b613fff811015612230576000915050610519565b6e0100000000000000000000000000006dffffffffffffffffffffffffffff608085901c161761406f82101561226c5761406f8290031c61229b565b61406f82111561229b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf9182011b5b6f80000000000000000000000000000000608085901c106122ef577f80000000000000000000000000000000000000000000000000000000000000008111156122e357600080fd5b60000391506105199050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81111561231c57600080fd5b91506105199050565b60006f80000000000000000000000000000000608083901c111561236a57507f7fff800000000000000000000000000000000000000000000000000000000000610519565b7f3fff0000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffff00000000000000000000000000000000831614156123bc57506000610519565b617fff60f083901c8116908114156123d75782915050610519565b6dffffffffffffffffffffffffffff608084901c16816123fa576001915061240c565b6e010000000000000000000000000000175b8061243c57507fffff00000000000000000000000000000000000000000000000000000000000091506105199050565b600061406f81613fff851061247f5750600f9290921b91600091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00184016124c9565b600192506e01000000000000000000000000000084106124ac5784613ffe039050600f84901b93506124c9565b60006124b785612152565b607f8190039590951b9461406d039150505b836f8000000000000000000000000000000014156125095782156124eb576001015b60006124f682612152565b60700392839003929190911b9050612580565b60008361251757600061251a565b60015b60ff1690505b6e01000000000000000000000000000082101561257e5793800260ff81901c607f81019190911c947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff939093019260019290921b9082180190612520565b505b806dffffffffffffffffffffffffffff16607083901b846125a25760006125b4565b6f800000000000000000000000000000005b6fffffffffffffffffffffffffffffffff16171760801b95505050505050610519565b60006f80000000000000000000000000000000608083901c90811190617fff60f085901c8116916dffffffffffffffffffffffffffff16908214801561261c57508015155b1561264d57507f7fff8000000000000000000000000000000000000000000000000000000000009250610519915050565b61400d82111561268f5782612682577f7fff000000000000000000000000000000000000000000000000000000000000612685565b60005b9350505050610519565b613f7f8210156126c557507f3fff0000000000000000000000000000000000000000000000000000000000009250610519915050565b816126d357600191506126e5565b6e010000000000000000000000000000175b613fef821115612718577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01182011b61272a565b613fef82101561272a57613fef8290031c5b828015612748575071406e0000000000000000000000000000000081115b1561275a575060009250610519915050565b821580156127795750713fffffffffffffffffffffffffffffffffff81115b156127aa57507f7fff0000000000000000000000000000000000000000000000000000000000009250610519915050565b6fffffffffffffffffffffffffffffffff81169060801c8380156127cd57508115155b156127d9579019906001015b6f80000000000000000000000000000000828116156128095770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6f40000000000000000000000000000000831615612838577001306fe0a31b7152de8d5a46305c85edec0260801c5b6f20000000000000000000000000000000831615612867577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6f100000000000000000000000000000008316156128965770010b5586cf9890f6298b92b71842a983630260801c5b6f080000000000000000000000000000008316156128c5577001059b0d31585743ae7c548eb68ca417fd0260801c5b6f040000000000000000000000000000008316156128f457700102c9a3e778060ee6f7caca4f7a29bde80260801c5b6f020000000000000000000000000000008316156129235770010163da9fb33356d84a66ae336dcdfa3f0260801c5b6f0100000000000000000000000000000083161561295257700100b1afa5abcbed6129ab13ec11dc95430260801c5b6e8000000000000000000000000000008316156129805770010058c86da1c09ea1ff19d294cf2f679b0260801c5b6e4000000000000000000000000000008316156129ae577001002c605e2e8cec506d21bfc89a23a00f0260801c5b6e2000000000000000000000000000008316156129dc57700100162f3904051fa128bca9c55c31e5df0260801c5b6e100000000000000000000000000000831615612a0a577001000b175effdc76ba38e31671ca9397250260801c5b6e080000000000000000000000000000831615612a3857700100058ba01fb9f96d6cacd4b180917c3d0260801c5b6e040000000000000000000000000000831615612a665770010002c5cc37da9491d0985c348c68e7b30260801c5b6e020000000000000000000000000000831615612a94577001000162e525ee054754457d59952920260260801c5b6e010000000000000000000000000000831615612ac25770010000b17255775c040618bf4a4ade83fc0260801c5b6d8000000000000000000000000000831615612aef577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6d4000000000000000000000000000831615612b1c57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6d2000000000000000000000000000831615612b495770010000162e43f4f831060e02d839a9d16d0260801c5b6d1000000000000000000000000000831615612b7657700100000b1721bcfc99d9f890ea069117630260801c5b6d0800000000000000000000000000831615612ba35770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6d0400000000000000000000000000831615612bd0577001000002c5c863b73f016468f6bac5ca2b0260801c5b6d0200000000000000000000000000831615612bfd57700100000162e430e5a18f6119e3c02282a50260801c5b6d0100000000000000000000000000831615612c2a577001000000b1721835514b86e6d96efd1bfe0260801c5b6c80000000000000000000000000831615612c5657700100000058b90c0b48c6be5df846c5b2ef0260801c5b6c40000000000000000000000000831615612c825770010000002c5c8601cc6b9e94213c72737a0260801c5b6c20000000000000000000000000831615612cae577001000000162e42fff037df38aa2b219f060260801c5b6c10000000000000000000000000831615612cda5770010000000b17217fba9c739aa5819f44f90260801c5b6c08000000000000000000000000831615612d06577001000000058b90bfcdee5acd3c1cedc8230260801c5b6c04000000000000000000000000831615612d3257700100000002c5c85fe31f35a6a30da1be500260801c5b6c02000000000000000000000000831615612d5e5770010000000162e42ff0999ce3541b9fffcf0260801c5b6c01000000000000000000000000831615612d8a57700100000000b17217f80f4ef5aadda455540260801c5b6b800000000000000000000000831615612db55770010000000058b90bfbf8479bd5a81b51ad0260801c5b6b400000000000000000000000831615612de0577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6b200000000000000000000000831615612e0b57700100000000162e42fefb2fed257559bdaa0260801c5b6b100000000000000000000000831615612e36577001000000000b17217f7d5a7716bba4a9ae0260801c5b6b080000000000000000000000831615612e6157700100000000058b90bfbe9ddbac5e109cce0260801c5b6b040000000000000000000000831615612e8c5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b6b020000000000000000000000831615612eb7577001000000000162e42fefa494f1478fde050260801c5b6b010000000000000000000000831615612ee25770010000000000b17217f7d20cf927c8e94c0260801c5b6a8000000000000000000000831615612f0c577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6a4000000000000000000000831615612f3657700100000000002c5c85fdf477b662b269450260801c5b6a2000000000000000000000831615612f605770010000000000162e42fefa3ae53369388c0260801c5b6a1000000000000000000000831615612f8a57700100000000000b17217f7d1d351a389d400260801c5b6a0800000000000000000000831615612fb45770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6a0400000000000000000000831615612fde577001000000000002c5c85fdf4741bea6e77e0260801c5b6a020000000000000000000083161561300857700100000000000162e42fefa39fe95583c20260801c5b6a0100000000000000000000831615613032577001000000000000b17217f7d1cfb72b45e10260801c5b698000000000000000000083161561305b57700100000000000058b90bfbe8e7cc35c3f00260801c5b69400000000000000000008316156130845770010000000000002c5c85fdf473e242ea380260801c5b69200000000000000000008316156130ad577001000000000000162e42fefa39f02b772c0260801c5b69100000000000000000008316156130d65770010000000000000b17217f7d1cf7d83c1a0260801c5b69080000000000000000008316156130ff577001000000000000058b90bfbe8e7bdcbe2e0260801c5b690400000000000000000083161561312857700100000000000002c5c85fdf473dea871f0260801c5b69020000000000000000008316156131515770010000000000000162e42fefa39ef44d910260801c5b690100000000000000000083161561317a57700100000000000000b17217f7d1cf79e9490260801c5b688000000000000000008316156131a25770010000000000000058b90bfbe8e7bce5440260801c5b684000000000000000008316156131ca577001000000000000002c5c85fdf473de6eca0260801c5b682000000000000000008316156131f257700100000000000000162e42fefa39ef366f0260801c5b6810000000000000000083161561321a577001000000000000000b17217f7d1cf79afa0260801c5b6808000000000000000083161561324257700100000000000000058b90bfbe8e7bcd6d0260801c5b6804000000000000000083161561326a5770010000000000000002c5c85fdf473de6b20260801c5b68020000000000000000831615613292577001000000000000000162e42fefa39ef3580260801c5b680100000000000000008316156132ba5770010000000000000000b17217f7d1cf79ab0260801c5b6780000000000000008316156132e1577001000000000000000058b90bfbe8e7bcd50260801c5b67400000000000000083161561330857700100000000000000002c5c85fdf473de6a0260801c5b67200000000000000083161561332f5770010000000000000000162e42fefa39ef340260801c5b67100000000000000083161561335657700100000000000000000b17217f7d1cf7990260801c5b67080000000000000083161561337d5770010000000000000000058b90bfbe8e7bcc0260801c5b6704000000000000008316156133a4577001000000000000000002c5c85fdf473de50260801c5b6702000000000000008316156133cb57700100000000000000000162e42fefa39ef20260801c5b6701000000000000008316156133f2577001000000000000000000b17217f7d1cf780260801c5b668000000000000083161561341857700100000000000000000058b90bfbe8e7bb0260801c5b664000000000000083161561343e5770010000000000000000002c5c85fdf473dd0260801c5b6620000000000000831615613464577001000000000000000000162e42fefa39ee0260801c5b661000000000000083161561348a5770010000000000000000000b17217f7d1cf60260801c5b66080000000000008316156134b0577001000000000000000000058b90bfbe8e7a0260801c5b66040000000000008316156134d657700100000000000000000002c5c85fdf473c0260801c5b66020000000000008316156134fc5770010000000000000000000162e42fefa39d0260801c5b660100000000000083161561352257700100000000000000000000b17217f7d1ce0260801c5b658000000000008316156135475770010000000000000000000058b90bfbe8e60260801c5b6540000000000083161561356c577001000000000000000000002c5c85fdf4720260801c5b6520000000000083161561359157700100000000000000000000162e42fefa380260801c5b651000000000008316156135b6577001000000000000000000000b17217f7d1b0260801c5b650800000000008316156135db57700100000000000000000000058b90bfbe8d0260801c5b650400000000008316156136005770010000000000000000000002c5c85fdf460260801c5b65020000000000831615613625577001000000000000000000000162e42fefa20260801c5b6501000000000083161561364a5770010000000000000000000000b17217f7d00260801c5b64800000000083161561366e577001000000000000000000000058b90bfbe70260801c5b64400000000083161561369257700100000000000000000000002c5c85fdf30260801c5b6420000000008316156136b65770010000000000000000000000162e42fef90260801c5b6410000000008316156136da57700100000000000000000000000b17217f7c0260801c5b6408000000008316156136fe5770010000000000000000000000058b90bfbd0260801c5b640400000000831615613722577001000000000000000000000002c5c85fde0260801c5b64020000000083161561374657700100000000000000000000000162e42fee0260801c5b64010000000083161561376a577001000000000000000000000000b17217f60260801c5b638000000083161561378d57700100000000000000000000000058b90bfa0260801c5b63400000008316156137b05770010000000000000000000000002c5c85fc0260801c5b63200000008316156137d3577001000000000000000000000000162e42fd0260801c5b63100000008316156137f65770010000000000000000000000000b17217e0260801c5b6308000000831615613819577001000000000000000000000000058b90be0260801c5b630400000083161561383c57700100000000000000000000000002c5c85e0260801c5b630200000083161561385f5770010000000000000000000000000162e42e0260801c5b630100000083161561388257700100000000000000000000000000b172160260801c5b628000008316156138a45770010000000000000000000000000058b90a0260801c5b624000008316156138c6577001000000000000000000000000002c5c840260801c5b622000008316156138e857700100000000000000000000000000162e410260801c5b6210000083161561390a577001000000000000000000000000000b17200260801c5b6208000083161561392c57700100000000000000000000000000058b8f0260801c5b6204000083161561394e5770010000000000000000000000000002c5c70260801c5b62020000831615613970577001000000000000000000000000000162e30260801c5b620100008316156139925770010000000000000000000000000000b1710260801c5b6180008316156139b3577001000000000000000000000000000058b80260801c5b6140008316156139d457700100000000000000000000000000002c5b0260801c5b6120008316156139f55770010000000000000000000000000000162d0260801c5b611000831615613a1657700100000000000000000000000000000b160260801c5b610800831615613a375770010000000000000000000000000000058a0260801c5b610400831615613a58577001000000000000000000000000000002c40260801c5b610200831615613a79577001000000000000000000000000000001610260801c5b610100831615613a9a577001000000000000000000000000000000b00260801c5b6080831615613aba577001000000000000000000000000000000570260801c5b6040831615613ada5770010000000000000000000000000000002b0260801c5b6020831615613afa577001000000000000000000000000000000150260801c5b6010831615613b1a5770010000000000000000000000000000000a0260801c5b6008831615613b3a577001000000000000000000000000000000040260801c5b6004831615613b5a577001000000000000000000000000000000010260801c5b84613b8257600f81901c6dffffffffffffffffffffffffffff169050613fff82019150613bd5565b613ffe8211613bae57600f81901c6dffffffffffffffffffffffffffff16905081613fff039150613bd5565b6000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc011011c5b60709190911b1760801b935061051992505050565b6000611ecc613bf9858561141c565b83613c0f565b6000611ecc84613c0f8585611860565b6000617fff60f084811c8216919084901c811690821415613c755780617fff1415613c6b577fffffffffffffffffffffffffffffffff0000000000000000000000000000000085811690851614156114f2578492505050610b4e565b8492505050610b4e565b80617fff1415613c89578392505050610b4e565b6f80000000000000000000000000000000608086901c90811015906dffffffffffffffffffffffffffff1683613cc25760019350613cd4565b6e010000000000000000000000000000175b6f80000000000000000000000000000000608087901c90811015906dffffffffffffffffffffffffffff1684613d0d5760019450613d1f565b6e010000000000000000000000000000175b82613d83577fffffffffffffffffffffffffffffffff0000000000000000000000000000000088167f800000000000000000000000000000000000000000000000000000000000000014613d735787613d76565b60005b9650505050505050610b4e565b80613dd7577fffffffffffffffffffffffffffffffff0000000000000000000000000000000089167f800000000000000000000000000000000000000000000000000000000000000014613d735788613d76565b8486038415158315151415613f65576070811315613dfe5789975050505050505050610b4e565b6000811315613e105790811c90613e5d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90811215613e475788975050505050505050610b4e565b6000811215613e5d578060000384901c93508596505b928101926e0200000000000000000000000000008410613e83576001968701969390931c925b86617fff1415613ee85784613eb8577f7fff000000000000000000000000000000000000000000000000000000000000613eda565b7fffff0000000000000000000000000000000000000000000000000000000000005b975050505050505050610b4e565b6e010000000000000000000000000000841015613f085760009650613f1c565b6dffffffffffffffffffffffffffff841693505b83607088901b86613f2e576000613f40565b6f800000000000000000000000000000005b6fffffffffffffffffffffffffffffffff16171760801b975050505050505050610b4e565b6000811315613f8057600184901b9350600187039650613f97565b6000811215613f9757600182901b91506001860396505b6070811315613fa95760019150614032565b6001811315613fc6576001810360018303901c6001019150614032565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90811215613ff75760019350614032565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811215614032576001816000030360018503901c60010193505b81841061404357818403935061404c565b83820393508294505b83614062575060009650610b4e95505050505050565b600061406d85612152565b9050806071141561409a57600185901c6dffffffffffffffffffffffffffff169450600188019750614115565b6070811015614101576070819003808911156140d0578086901b6dffffffffffffffffffffffffffff16955080890398506140fb565b6000987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019590951b945b50614115565b6dffffffffffffffffffffffffffff851694505b87617fff141561417b578561414a577f7fff00000000000000000000000000000000000000000000000000000000000061416c565b7fffff0000000000000000000000000000000000000000000000000000000000005b98505050505050505050610b4e565b84607089901b8761418d57600061419f565b6f800000000000000000000000000000005b6fffffffffffffffffffffffffffffffff16171760801b98505050505050505050610b4e56fea264697066735822122079b7ba8f10037609d0ecda44b47c4c3264cf2fb12d0d65a7ab2c5c200e5929f464736f6c63430007060033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80638e6f235311610097578063a598cef811610066578063a598cef8146102d3578063c36596a6146101f4578063dd43eb57146102f0578063ec093021146102f8576100f5565b80638e6f23531461022957806395d89b4114610246578063992e2a92146102c35780639a86139b146102cb576100f5565b806340179d83116100d357806340179d83146101f45780634dcd7dee146101fc578063665df4601461020457806373d1747b14610221576100f5565b806301032adc146100fa5780631a1afbc5146101145780631f072062146101d8575b600080fd5b610102610300565b60408051918252519081900360200190f35b6101b2600480360361010081101561012b57600080fd5b60408051808201825283359360208101359373ffffffffffffffffffffffffffffffffffffffff8483013516939082019260a0830191606084019060029083908390808284376000920191909152505060408051808201825292959493818101939250906002908390839080828437600092019190915250919450509035915061030c9050565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6101e06104b4565b604080519115158252519081900360200190f35b6101026104b9565b6101026104c5565b6101026004803603602081101561021a57600080fd5b50356104e9565b61010261051e565b6101026004803603602081101561023f57600080fd5b5035610532565b61024e610551565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610288578181015183820152602001610270565b50505050905090810190601f1680156102b55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610102610588565b610102610594565b610102600480360360208110156102e957600080fd5b50356105b8565b610102610743565b610102610748565b671bc16d674ec7ffff81565b600080808073ffffffffffffffffffffffffffffffffffffffff881661039357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a65726f206f7261636c65000000000000000000000000000000000000000000604482015290519081900360640190fd5b61043261039f89610758565b6103b1876103ac8c61098d565b610b23565b61042b8b73ffffffffffffffffffffffffffffffffffffffff166366101b646040518163ffffffff1660e01b815260040160206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d602081101561042457600080fd5b5051610b54565b8d8d610b6f565b9092509050600082670de0b6b3a764000083028161044c57fe5b059050600061046989600160200201518960016020020151610bb6565b905061049761049261048b836104868c6000602002015187610bb6565b610bb6565b8b51610cca565b6104e9565b95506104a38187610cca565b945050509650965096509692505050565b600190565b670de0b6b3a764000081565b7f800000000000000000000000000000000000000000000000000000000000000081565b600061051661050861050384670de0b6b3a7640000610e49565b610e67565b670de0b6b3a76400006110b1565b90505b919050565b6402540be400670de0b6b3a76400005b0481565b600061051661050861054c84670de0b6b3a7640000610e49565b6110cd565b60408051808201909152600a81527f7835526570726963657200000000000000000000000000000000000000000000602082015290565b6704a03ce68d21555681565b7f42524f4e5a45000000000000000000000000000000000000000000000000000090565b6000806105cd83670de0b6b3a7640000610e49565b905060006105da82611101565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106128361060d6025611126565b611192565b60000b148061062f575061062f8261062a6025611126565b611391565b156106c957600061066261065d61064e610648866113f7565b8661141c565b6106586002611126565b611860565b611c6d565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106a08461060d6602831c2082c9f3655af3107a4000610e49565b60000b14156106ba576106b38382611ca1565b91506106c7565b6106c48382611e43565b91505b505b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106f384611ed4565b60000b14806107085750610708836000611391565b6107245761071f6107196001611126565b82611f79565b610726565b805b905061073a81670de0b6b3a76400006110b1565b95945050505050565b600181565b6002670de0b6b3a764000061052e565b60008173ffffffffffffffffffffffffffffffffffffffff1663dbcb32bf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156107a057600080fd5b505afa1580156107b4573d6000803e3d6000fd5b505050506040513d60208110156107ca57600080fd5b5051604080517fab56c592000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163ab56c59291600480820192602092909190829003018186803b15801561083457600080fd5b505afa158015610848573d6000803e3d6000fd5b505050506040513d602081101561085e57600080fd5b5051604080517fdbcb32bf000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff85169163dbcb32bf916004808301926020929190829003018186803b1580156108c657600080fd5b505afa1580156108da573d6000803e3d6000fd5b505050506040513d60208110156108f057600080fd5b5051604080517fc6bb30e2000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163c6bb30e291600480820192602092909190829003018186803b15801561095a57600080fd5b505afa15801561096e573d6000803e3d6000fd5b505050506040513d602081101561098457600080fd5b50510192915050565b6000808273ffffffffffffffffffffffffffffffffffffffff16635b69a7d860006040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156109e257600080fd5b505afa1580156109f6573d6000803e3d6000fd5b505050506040513d6020811015610a0c57600080fd5b5051604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163feaf968c9160048082019260a092909190829003018186803b158015610a7657600080fd5b505afa158015610a8a573d6000803e3d6000fd5b505050506040513d60a0811015610aa057600080fd5b506020810151606090910151909250905080610b1d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f454d5054595f4f5241434c455f4c41544553545f524f554e4400000000000000604482015290519081900360640190fd5b50919050565b600082670de0b6b3a76400008484030281610b3a57fe5b05600502670de0b6b3a76400006005020190505b92915050565b60006301e13380428303670de0b6b3a7640000020592915050565b600080610b7d868685611fa7565b915083821215610b8b578391505b670de0b6b3a76400008702848103831315610ba65784810392505b8281039150509550959350505050565b6000828202831580610bd0575082848281610bcd57fe5b04145b610c3b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b6706f05b59d3b20000810181811015610cb557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a7640000815b0495945050505050565b600081610d3857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4449565f5a45524f000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a76400008302831580610d605750670de0b6b3a7640000848281610d5d57fe5b04145b610dcb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b60028304810181811015610e4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b838181610cc057fe5b6000610e60610e57846120b0565b61065884611126565b9392505050565b60006f80000000000000000000000000000000608083901c1115610eac57507f7fff800000000000000000000000000000000000000000000000000000000000610519565b617fff60f083901c811690811415610ec75782915050610519565b6dffffffffffffffffffffffffffff608084901c1681610eea5760019150610efc565b6e010000000000000000000000000000175b80610f0d5750600091506105199050565b613fff8201600190811c9216158015610f89576e0100000000000000000000000000008210610f4257607182901b9150610f84565b6000610f4d83612152565b60e20360fe167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810160011c909403939290921b91505b610fed565b6e0100000000000000000000000000008210610fab57607082901b9150610fed565b6000610fb683612152565b60e10360fe167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810160011c909403939290921b91505b6e01000000000000000000000000000080830401600190811c9081848161101057fe5b048201901c9050600181848161102257fe5b048201901c9050600181848161103457fe5b048201901c9050600181848161104657fe5b048201901c9050600181848161105857fe5b048201901c9050600181848161106a57fe5b048201901c9050600081848161107c57fe5b0490508181101561108b578091505b816dffffffffffffffffffffffffffff16607086901b1760801b95505050505050610519565b6000610e606110c8846110c385611126565b61141c565b612202565b60006105166110db83612325565b7f3ffe62e42fefa39ef35793c7673007e50000000000000000000000000000000061141c565b7f7fffffffffffffffffffffffffffffff000000000000000000000000000000001690565b60008161113557506000610519565b81600061114182612152565b9050607081101561115a578060700382901b915061116d565b607081111561116d576070810382901c91505b613fff0160701b6dffffffffffffffffffffffffffff919091161760801b9050610519565b60006f7fffffffffffffffffffffffffffffff608084901c166f7fff00000000000000000000000000008111156111c857600080fd5b6f7fffffffffffffffffffffffffffffff608084901c166f7fff00000000000000000000000000008111156111fc57600080fd5b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000085811690851614158061125157506f7fff0000000000000000000000000000826fffffffffffffffffffffffffffffffff16105b61125a57600080fd5b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000858116908516141561129257600092505050610b4e565b6f80000000000000000000000000000000608086811c82118015929187901c9190911015906113205780156112f357826fffffffffffffffffffffffffffffffff16846fffffffffffffffffffffffffffffffff16116112f3576001611315565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b945050505050610b4e565b8015611333576001945050505050610b4e565b826fffffffffffffffffffffffffffffffff16846fffffffffffffffffffffffffffffffff1611611384577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611315565b6001945050505050610b4e565b60007fffffffffffffffffffffffffffffffff0000000000000000000000000000000083811690831614156113ef57506f7fff00000000000000000000000000006f7fffffffffffffffffffffffffffffff608084901c1610610b4e565b506000610b4e565b7f80000000000000000000000000000000000000000000000000000000000000001890565b6000617fff60f084811c8216919084901c81169082141561159c5780617fff141561151d577fffffffffffffffffffffffffffffffff00000000000000000000000000000000858116908516141561149b575050507f800000000000000000000000000000000000000000000000000000000000000081168218610b4e565b7f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffff000000000000000000000000000000008686181614156114f257505050818117610b4e565b507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b7f7fffffffffffffffffffffffffffffff00000000000000000000000000000000841661156f57507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050507f800000000000000000000000000000000000000000000000000000000000000081168218610b4e565b80617fff1415611625577f7fffffffffffffffffffffffffffffff0000000000000000000000000000000085166115f857507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050507f800000000000000000000000000000000000000000000000000000000000000082168118610b4e565b6dffffffffffffffffffffffffffff608086901c1682611648576001925061165a565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608086901c168261167d576001925061168f565b6e010000000000000000000000000000175b90810290816116f4577f8000000000000000000000000000000000000000000000000000000000000000878718166116c8576000611315565b7f8000000000000000000000000000000000000000000000000000000000000000945050505050610b4e565b9282019260007c020000000000000000000000000000000000000000000000000000000083101561175a577c01000000000000000000000000000000000000000000000000000000008310156117525761174d83612152565b611755565b60e05b61175d565b60e15b9050614070818601101561177857600094506000925061181c565b6140e081860110156117bb5761407085101561179d57846140700383901c92506117b2565b6140708511156117b257614070850383901b92505b6000945061181c565b61c0dd81860111156117d557617fff94506000925061181c565b60708111156117ec576070810383901c92506117ff565b60708110156117ff578060700383901b92505b6dffffffffffffffffffffffffffff831692506140df8186010394505b82607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610b4e565b6000617fff60f084811c8216919084901c8116908214156118b05780617fff141561156f57507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b80617fff1415611938577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561190b57507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050508082187f800000000000000000000000000000000000000000000000000000000000000016610b4e565b7f7fffffffffffffffffffffffffffffff000000000000000000000000000000008416611a00577f7fffffffffffffffffffffffffffffff0000000000000000000000000000000085166119b157507f7fff8000000000000000000000000000000000000000000000000000000000009150610b4e9050565b5050508082187f8000000000000000000000000000000000000000000000000000000000000000167f7fff00000000000000000000000000000000000000000000000000000000000017610b4e565b6dffffffffffffffffffffffffffff608085901c1681611a235760019150611a35565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608087901c1683611a99578015611a94576000611a6082612152565b6001955060e2039384017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e01939190911b90505b611aae565b6e0100000000000000000000000000001760721b5b818181611ab757fe5b04905080611aef577f8000000000000000000000000000000000000000000000000000000000000000878718166116c8576000611315565b6d1000000000000000000000000000811015611b0757fe5b60006e080000000000000000000000000000821015611b68576e040000000000000000000000000000821015611b5d576e020000000000000000000000000000821015611b55576070611b58565b60715b611b60565b60725b60ff16611b71565b611b7182612152565b905083614071018186011115611b8f57617fff945060009150611c29565b83818601613ffc011015611baa576000945060009150611c29565b83818601613f8c011015611bf7578385613ffc011115611bd5578385613ffc010382901b9150611bee565b8385613ffc011015611bee57613ffc8585030382901c91505b60009450611c29565b6070811115611c0a576070810382901c91505b6dffffffffffffffffffffffffffff8216915083818601613f8d010394505b81607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610b4e565b6000610516611c9c837f3fff71547652b82fe1777d0ffda0d23a0000000000000000000000000000000061141c565b6125d7565b600080611d5c611d46611d30611d1a611d04611cec611cce660140b5e5d6593f662386f26fc10000610e49565b8a611ce766027cfea3c34b2866038d7ea4c68000610e49565b613bea565b89611ce7660243b55f4b9a8d655af3107a4000610e49565b88611ce7651ed7f455feaf64e8d4a51000610e49565b87611ce76565ef7e5b3d8f64e8d4a51000610e49565b86611ce765c9314dd1b6cb64e8d4a51000610e49565b85611ce765c846e82396b864e8d4a51000610e49565b90506000611e2e611e17611e00611de9611dd2611dba611da4611d8d660323e328a37c70662386f26fc10000610e49565b8c611ce7659fad4fc2b238655af3107a4000610e49565b8b611ce7650e9c3b9924c764e8d4a51000610e49565b8a611ce7660315442329bd956509184e72a000610e49565b89611ce766010db93eb39b9a64e8d4a51000610e49565b88611ce7660243a6ccd22a0f64e8d4a51000610e49565b87611ce76602d1fb234ac30c64e8d4a51000610e49565b86611ce76601908dd0472d7064e8d4a51000610e49565b905061073a611e3d858461141c565b82611860565b600080611e6384611e54600d611126565b611e5e6014611126565b613bff565b9050611e7984611e736004611126565b83613bff565b9050611e8984611e736003611126565b9050611e9984611e736002611126565b9050611ea984611e736001611126565b9050611ecc83610658611ec6643a5cab35c764174876e800610e49565b84611860565b949350505050565b60006f7fffffffffffffffffffffffffffffff608083901c166f7fff0000000000000000000000000000811115611f0a57600080fd5b6fffffffffffffffffffffffffffffffff8116611f2b576000915050610519565b6f80000000000000000000000000000000608084901c10611f6f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915050610519565b6001915050610519565b6000610e60837f80000000000000000000000000000000000000000000000000000000000000008418613c0f565b600080670de0b6b3a7640000611fbc856104e9565b840281611fc557fe5b0590506000816ec097ce7bc90715b34b9f100000000081611fe257fe5b0590506f01812f9cf7920e2b66973e20000000008480028602056000670de0b6b3a76400008261201560048b5b05610532565b0184028161201f57fe5b059050600061202f8583036105b8565b600402670de0b6b3a76400008a612045856105b8565b028161204d57fe5b05039050670de0b6b3a76400008361206660068c61200f565b0185028161207057fe5b05915060006120808684036105b8565b600602670de0b6b3a76400008b612096866105b8565b028161209e57fe5b05039091039998505050505050505050565b6000816120bf57506000610519565b60008083136120d157826000036120d3565b825b905060006120e082612152565b905060708110156120f9578060700382901b915061210c565b607081111561210c576070810382901c91505b6dffffffffffffffffffffffffffff909116613fff820160701b17906000841215612147576f80000000000000000000000000000000821791505b5060801b9050610519565b600080821161216057600080fd5b6000700100000000000000000000000000000000831061218257608092831c92015b68010000000000000000831061219a57604092831c92015b64010000000083106121ae57602092831c92015b6201000083106121c057601092831c92015b61010083106121d157600892831c92015b601083106121e157600492831c92015b600483106121f157600292831c92015b600283106105165760010192915050565b6000617fff60f083901c166140fe81111561221c57600080fd5b613fff811015612230576000915050610519565b6e0100000000000000000000000000006dffffffffffffffffffffffffffff608085901c161761406f82101561226c5761406f8290031c61229b565b61406f82111561229b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf9182011b5b6f80000000000000000000000000000000608085901c106122ef577f80000000000000000000000000000000000000000000000000000000000000008111156122e357600080fd5b60000391506105199050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81111561231c57600080fd5b91506105199050565b60006f80000000000000000000000000000000608083901c111561236a57507f7fff800000000000000000000000000000000000000000000000000000000000610519565b7f3fff0000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffff00000000000000000000000000000000831614156123bc57506000610519565b617fff60f083901c8116908114156123d75782915050610519565b6dffffffffffffffffffffffffffff608084901c16816123fa576001915061240c565b6e010000000000000000000000000000175b8061243c57507fffff00000000000000000000000000000000000000000000000000000000000091506105199050565b600061406f81613fff851061247f5750600f9290921b91600091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00184016124c9565b600192506e01000000000000000000000000000084106124ac5784613ffe039050600f84901b93506124c9565b60006124b785612152565b607f8190039590951b9461406d039150505b836f8000000000000000000000000000000014156125095782156124eb576001015b60006124f682612152565b60700392839003929190911b9050612580565b60008361251757600061251a565b60015b60ff1690505b6e01000000000000000000000000000082101561257e5793800260ff81901c607f81019190911c947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff939093019260019290921b9082180190612520565b505b806dffffffffffffffffffffffffffff16607083901b846125a25760006125b4565b6f800000000000000000000000000000005b6fffffffffffffffffffffffffffffffff16171760801b95505050505050610519565b60006f80000000000000000000000000000000608083901c90811190617fff60f085901c8116916dffffffffffffffffffffffffffff16908214801561261c57508015155b1561264d57507f7fff8000000000000000000000000000000000000000000000000000000000009250610519915050565b61400d82111561268f5782612682577f7fff000000000000000000000000000000000000000000000000000000000000612685565b60005b9350505050610519565b613f7f8210156126c557507f3fff0000000000000000000000000000000000000000000000000000000000009250610519915050565b816126d357600191506126e5565b6e010000000000000000000000000000175b613fef821115612718577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01182011b61272a565b613fef82101561272a57613fef8290031c5b828015612748575071406e0000000000000000000000000000000081115b1561275a575060009250610519915050565b821580156127795750713fffffffffffffffffffffffffffffffffff81115b156127aa57507f7fff0000000000000000000000000000000000000000000000000000000000009250610519915050565b6fffffffffffffffffffffffffffffffff81169060801c8380156127cd57508115155b156127d9579019906001015b6f80000000000000000000000000000000828116156128095770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6f40000000000000000000000000000000831615612838577001306fe0a31b7152de8d5a46305c85edec0260801c5b6f20000000000000000000000000000000831615612867577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6f100000000000000000000000000000008316156128965770010b5586cf9890f6298b92b71842a983630260801c5b6f080000000000000000000000000000008316156128c5577001059b0d31585743ae7c548eb68ca417fd0260801c5b6f040000000000000000000000000000008316156128f457700102c9a3e778060ee6f7caca4f7a29bde80260801c5b6f020000000000000000000000000000008316156129235770010163da9fb33356d84a66ae336dcdfa3f0260801c5b6f0100000000000000000000000000000083161561295257700100b1afa5abcbed6129ab13ec11dc95430260801c5b6e8000000000000000000000000000008316156129805770010058c86da1c09ea1ff19d294cf2f679b0260801c5b6e4000000000000000000000000000008316156129ae577001002c605e2e8cec506d21bfc89a23a00f0260801c5b6e2000000000000000000000000000008316156129dc57700100162f3904051fa128bca9c55c31e5df0260801c5b6e100000000000000000000000000000831615612a0a577001000b175effdc76ba38e31671ca9397250260801c5b6e080000000000000000000000000000831615612a3857700100058ba01fb9f96d6cacd4b180917c3d0260801c5b6e040000000000000000000000000000831615612a665770010002c5cc37da9491d0985c348c68e7b30260801c5b6e020000000000000000000000000000831615612a94577001000162e525ee054754457d59952920260260801c5b6e010000000000000000000000000000831615612ac25770010000b17255775c040618bf4a4ade83fc0260801c5b6d8000000000000000000000000000831615612aef577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6d4000000000000000000000000000831615612b1c57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6d2000000000000000000000000000831615612b495770010000162e43f4f831060e02d839a9d16d0260801c5b6d1000000000000000000000000000831615612b7657700100000b1721bcfc99d9f890ea069117630260801c5b6d0800000000000000000000000000831615612ba35770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6d0400000000000000000000000000831615612bd0577001000002c5c863b73f016468f6bac5ca2b0260801c5b6d0200000000000000000000000000831615612bfd57700100000162e430e5a18f6119e3c02282a50260801c5b6d0100000000000000000000000000831615612c2a577001000000b1721835514b86e6d96efd1bfe0260801c5b6c80000000000000000000000000831615612c5657700100000058b90c0b48c6be5df846c5b2ef0260801c5b6c40000000000000000000000000831615612c825770010000002c5c8601cc6b9e94213c72737a0260801c5b6c20000000000000000000000000831615612cae577001000000162e42fff037df38aa2b219f060260801c5b6c10000000000000000000000000831615612cda5770010000000b17217fba9c739aa5819f44f90260801c5b6c08000000000000000000000000831615612d06577001000000058b90bfcdee5acd3c1cedc8230260801c5b6c04000000000000000000000000831615612d3257700100000002c5c85fe31f35a6a30da1be500260801c5b6c02000000000000000000000000831615612d5e5770010000000162e42ff0999ce3541b9fffcf0260801c5b6c01000000000000000000000000831615612d8a57700100000000b17217f80f4ef5aadda455540260801c5b6b800000000000000000000000831615612db55770010000000058b90bfbf8479bd5a81b51ad0260801c5b6b400000000000000000000000831615612de0577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6b200000000000000000000000831615612e0b57700100000000162e42fefb2fed257559bdaa0260801c5b6b100000000000000000000000831615612e36577001000000000b17217f7d5a7716bba4a9ae0260801c5b6b080000000000000000000000831615612e6157700100000000058b90bfbe9ddbac5e109cce0260801c5b6b040000000000000000000000831615612e8c5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b6b020000000000000000000000831615612eb7577001000000000162e42fefa494f1478fde050260801c5b6b010000000000000000000000831615612ee25770010000000000b17217f7d20cf927c8e94c0260801c5b6a8000000000000000000000831615612f0c577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6a4000000000000000000000831615612f3657700100000000002c5c85fdf477b662b269450260801c5b6a2000000000000000000000831615612f605770010000000000162e42fefa3ae53369388c0260801c5b6a1000000000000000000000831615612f8a57700100000000000b17217f7d1d351a389d400260801c5b6a0800000000000000000000831615612fb45770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6a0400000000000000000000831615612fde577001000000000002c5c85fdf4741bea6e77e0260801c5b6a020000000000000000000083161561300857700100000000000162e42fefa39fe95583c20260801c5b6a0100000000000000000000831615613032577001000000000000b17217f7d1cfb72b45e10260801c5b698000000000000000000083161561305b57700100000000000058b90bfbe8e7cc35c3f00260801c5b69400000000000000000008316156130845770010000000000002c5c85fdf473e242ea380260801c5b69200000000000000000008316156130ad577001000000000000162e42fefa39f02b772c0260801c5b69100000000000000000008316156130d65770010000000000000b17217f7d1cf7d83c1a0260801c5b69080000000000000000008316156130ff577001000000000000058b90bfbe8e7bdcbe2e0260801c5b690400000000000000000083161561312857700100000000000002c5c85fdf473dea871f0260801c5b69020000000000000000008316156131515770010000000000000162e42fefa39ef44d910260801c5b690100000000000000000083161561317a57700100000000000000b17217f7d1cf79e9490260801c5b688000000000000000008316156131a25770010000000000000058b90bfbe8e7bce5440260801c5b684000000000000000008316156131ca577001000000000000002c5c85fdf473de6eca0260801c5b682000000000000000008316156131f257700100000000000000162e42fefa39ef366f0260801c5b6810000000000000000083161561321a577001000000000000000b17217f7d1cf79afa0260801c5b6808000000000000000083161561324257700100000000000000058b90bfbe8e7bcd6d0260801c5b6804000000000000000083161561326a5770010000000000000002c5c85fdf473de6b20260801c5b68020000000000000000831615613292577001000000000000000162e42fefa39ef3580260801c5b680100000000000000008316156132ba5770010000000000000000b17217f7d1cf79ab0260801c5b6780000000000000008316156132e1577001000000000000000058b90bfbe8e7bcd50260801c5b67400000000000000083161561330857700100000000000000002c5c85fdf473de6a0260801c5b67200000000000000083161561332f5770010000000000000000162e42fefa39ef340260801c5b67100000000000000083161561335657700100000000000000000b17217f7d1cf7990260801c5b67080000000000000083161561337d5770010000000000000000058b90bfbe8e7bcc0260801c5b6704000000000000008316156133a4577001000000000000000002c5c85fdf473de50260801c5b6702000000000000008316156133cb57700100000000000000000162e42fefa39ef20260801c5b6701000000000000008316156133f2577001000000000000000000b17217f7d1cf780260801c5b668000000000000083161561341857700100000000000000000058b90bfbe8e7bb0260801c5b664000000000000083161561343e5770010000000000000000002c5c85fdf473dd0260801c5b6620000000000000831615613464577001000000000000000000162e42fefa39ee0260801c5b661000000000000083161561348a5770010000000000000000000b17217f7d1cf60260801c5b66080000000000008316156134b0577001000000000000000000058b90bfbe8e7a0260801c5b66040000000000008316156134d657700100000000000000000002c5c85fdf473c0260801c5b66020000000000008316156134fc5770010000000000000000000162e42fefa39d0260801c5b660100000000000083161561352257700100000000000000000000b17217f7d1ce0260801c5b658000000000008316156135475770010000000000000000000058b90bfbe8e60260801c5b6540000000000083161561356c577001000000000000000000002c5c85fdf4720260801c5b6520000000000083161561359157700100000000000000000000162e42fefa380260801c5b651000000000008316156135b6577001000000000000000000000b17217f7d1b0260801c5b650800000000008316156135db57700100000000000000000000058b90bfbe8d0260801c5b650400000000008316156136005770010000000000000000000002c5c85fdf460260801c5b65020000000000831615613625577001000000000000000000000162e42fefa20260801c5b6501000000000083161561364a5770010000000000000000000000b17217f7d00260801c5b64800000000083161561366e577001000000000000000000000058b90bfbe70260801c5b64400000000083161561369257700100000000000000000000002c5c85fdf30260801c5b6420000000008316156136b65770010000000000000000000000162e42fef90260801c5b6410000000008316156136da57700100000000000000000000000b17217f7c0260801c5b6408000000008316156136fe5770010000000000000000000000058b90bfbd0260801c5b640400000000831615613722577001000000000000000000000002c5c85fde0260801c5b64020000000083161561374657700100000000000000000000000162e42fee0260801c5b64010000000083161561376a577001000000000000000000000000b17217f60260801c5b638000000083161561378d57700100000000000000000000000058b90bfa0260801c5b63400000008316156137b05770010000000000000000000000002c5c85fc0260801c5b63200000008316156137d3577001000000000000000000000000162e42fd0260801c5b63100000008316156137f65770010000000000000000000000000b17217e0260801c5b6308000000831615613819577001000000000000000000000000058b90be0260801c5b630400000083161561383c57700100000000000000000000000002c5c85e0260801c5b630200000083161561385f5770010000000000000000000000000162e42e0260801c5b630100000083161561388257700100000000000000000000000000b172160260801c5b628000008316156138a45770010000000000000000000000000058b90a0260801c5b624000008316156138c6577001000000000000000000000000002c5c840260801c5b622000008316156138e857700100000000000000000000000000162e410260801c5b6210000083161561390a577001000000000000000000000000000b17200260801c5b6208000083161561392c57700100000000000000000000000000058b8f0260801c5b6204000083161561394e5770010000000000000000000000000002c5c70260801c5b62020000831615613970577001000000000000000000000000000162e30260801c5b620100008316156139925770010000000000000000000000000000b1710260801c5b6180008316156139b3577001000000000000000000000000000058b80260801c5b6140008316156139d457700100000000000000000000000000002c5b0260801c5b6120008316156139f55770010000000000000000000000000000162d0260801c5b611000831615613a1657700100000000000000000000000000000b160260801c5b610800831615613a375770010000000000000000000000000000058a0260801c5b610400831615613a58577001000000000000000000000000000002c40260801c5b610200831615613a79577001000000000000000000000000000001610260801c5b610100831615613a9a577001000000000000000000000000000000b00260801c5b6080831615613aba577001000000000000000000000000000000570260801c5b6040831615613ada5770010000000000000000000000000000002b0260801c5b6020831615613afa577001000000000000000000000000000000150260801c5b6010831615613b1a5770010000000000000000000000000000000a0260801c5b6008831615613b3a577001000000000000000000000000000000040260801c5b6004831615613b5a577001000000000000000000000000000000010260801c5b84613b8257600f81901c6dffffffffffffffffffffffffffff169050613fff82019150613bd5565b613ffe8211613bae57600f81901c6dffffffffffffffffffffffffffff16905081613fff039150613bd5565b6000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc011011c5b60709190911b1760801b935061051992505050565b6000611ecc613bf9858561141c565b83613c0f565b6000611ecc84613c0f8585611860565b6000617fff60f084811c8216919084901c811690821415613c755780617fff1415613c6b577fffffffffffffffffffffffffffffffff0000000000000000000000000000000085811690851614156114f2578492505050610b4e565b8492505050610b4e565b80617fff1415613c89578392505050610b4e565b6f80000000000000000000000000000000608086901c90811015906dffffffffffffffffffffffffffff1683613cc25760019350613cd4565b6e010000000000000000000000000000175b6f80000000000000000000000000000000608087901c90811015906dffffffffffffffffffffffffffff1684613d0d5760019450613d1f565b6e010000000000000000000000000000175b82613d83577fffffffffffffffffffffffffffffffff0000000000000000000000000000000088167f800000000000000000000000000000000000000000000000000000000000000014613d735787613d76565b60005b9650505050505050610b4e565b80613dd7577fffffffffffffffffffffffffffffffff0000000000000000000000000000000089167f800000000000000000000000000000000000000000000000000000000000000014613d735788613d76565b8486038415158315151415613f65576070811315613dfe5789975050505050505050610b4e565b6000811315613e105790811c90613e5d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90811215613e475788975050505050505050610b4e565b6000811215613e5d578060000384901c93508596505b928101926e0200000000000000000000000000008410613e83576001968701969390931c925b86617fff1415613ee85784613eb8577f7fff000000000000000000000000000000000000000000000000000000000000613eda565b7fffff0000000000000000000000000000000000000000000000000000000000005b975050505050505050610b4e565b6e010000000000000000000000000000841015613f085760009650613f1c565b6dffffffffffffffffffffffffffff841693505b83607088901b86613f2e576000613f40565b6f800000000000000000000000000000005b6fffffffffffffffffffffffffffffffff16171760801b975050505050505050610b4e565b6000811315613f8057600184901b9350600187039650613f97565b6000811215613f9757600182901b91506001860396505b6070811315613fa95760019150614032565b6001811315613fc6576001810360018303901c6001019150614032565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90811215613ff75760019350614032565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811215614032576001816000030360018503901c60010193505b81841061404357818403935061404c565b83820393508294505b83614062575060009650610b4e95505050505050565b600061406d85612152565b9050806071141561409a57600185901c6dffffffffffffffffffffffffffff169450600188019750614115565b6070811015614101576070819003808911156140d0578086901b6dffffffffffffffffffffffffffff16955080890398506140fb565b6000987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019590951b945b50614115565b6dffffffffffffffffffffffffffff851694505b87617fff141561417b578561414a577f7fff00000000000000000000000000000000000000000000000000000000000061416c565b7fffff0000000000000000000000000000000000000000000000000000000000005b98505050505050505050610b4e565b84607089901b8761418d57600061419f565b6f800000000000000000000000000000005b6fffffffffffffffffffffffffffffffff16171760801b98505050505050505050610b4e56fea264697066735822122079b7ba8f10037609d0ecda44b47c4c3264cf2fb12d0d65a7ab2c5c200e5929f464736f6c63430007060033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.