Contract

0x0A11E980Cab9da65846840A8cfa4340cE80b00bC

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

-

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Update I Vs30995692025-01-09 10:00:389 mins ago1736416838IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30975552025-01-09 9:30:2939 mins ago1736415029IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30953242025-01-09 9:00:281 hr ago1736413228IN
0x0A11E980...cE80b00bC
0 S0.000319175
Update I Vs30924762025-01-09 8:30:121 hr ago1736411412IN
0x0A11E980...cE80b00bC
0 S0.000319175
Update I Vs30896182025-01-09 8:01:002 hrs ago1736409660IN
0x0A11E980...cE80b00bC
0 S0.000512138.02277453
Update I Vs30862162025-01-09 7:30:042 hrs ago1736407804IN
0x0A11E980...cE80b00bC
0 S0.000395736.48369828
Update I Vs30829332025-01-09 7:00:233 hrs ago1736406023IN
0x0A11E980...cE80b00bC
0 S0.0007761912.15947192
Update I Vs30803992025-01-09 6:30:123 hrs ago1736404212IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30780822025-01-09 6:00:144 hrs ago1736402414IN
0x0A11E980...cE80b00bC
0 S0.000235175
Update I Vs30759312025-01-09 5:30:284 hrs ago1736400628IN
0x0A11E980...cE80b00bC
0 S0.000235175
Update I Vs30738952025-01-09 5:00:125 hrs ago1736398812IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30718542025-01-09 4:30:075 hrs ago1736397007IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30699562025-01-09 4:00:096 hrs ago1736395209IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30682742025-01-09 3:30:466 hrs ago1736393446IN
0x0A11E980...cE80b00bC
0 S0.000336095.50666666
Update I Vs30662682025-01-09 3:00:107 hrs ago1736391610IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30642912025-01-09 2:30:067 hrs ago1736389806IN
0x0A11E980...cE80b00bC
0 S0.000319175
Update I Vs30615052025-01-09 2:00:138 hrs ago1736388013IN
0x0A11E980...cE80b00bC
0 S0.000235175
Update I Vs30593972025-01-09 1:30:118 hrs ago1736386211IN
0x0A11E980...cE80b00bC
0 S0.000319235.001
Update I Vs30564982025-01-09 1:00:169 hrs ago1736384416IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30533712025-01-09 0:30:319 hrs ago1736382631IN
0x0A11E980...cE80b00bC
0 S0.000319175
Update I Vs30505472025-01-09 0:00:3010 hrs ago1736380830IN
0x0A11E980...cE80b00bC
0 S0.000305175
Update I Vs30474862025-01-08 23:30:0710 hrs ago1736379007IN
0x0A11E980...cE80b00bC
0 S0.000319175
Update I Vs30098022025-01-08 17:01:1817 hrs ago1736355678IN
0x0A11E980...cE80b00bC
0 S0.000235175
Update I Vs30063252025-01-08 16:30:3517 hrs ago1736353835IN
0x0A11E980...cE80b00bC
0 S0.000322366.85377013
Update I Vs30032282025-01-08 16:00:4518 hrs ago1736352045IN
0x0A11E980...cE80b00bC
0 S0.000319175
View all transactions

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

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x2921907f...9173abC34
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
OptionPricingLinearV2_1

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 0 runs

Other Settings:
london EvmVersion
File 1 of 7 : OptionPricingLinearV2_1.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

// Libraries
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {BlackScholes} from "./external/BlackScholes.sol";
import {ABDKMathQuad} from "./external/ABDKMathQuad.sol";

// Contracts
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

// Interfaces
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract OptionPricingLinearV2_1 is Ownable {
    using SafeMath for uint256;

    // The % of the price of asset which is the minimum option price possible in 1e8 precision
    uint256 public minOptionPricePercentage;

    // The decimal precision for volatility calculation
    uint256 public constant VOLATILITY_PRECISION = 1e4;

    // xSYK token address
    address public xSyk;

    // Time to expiry => volatility
    mapping(uint256 => uint256) public ttlToVol;

    // TTL => The offset for volatility calculation in 1e4 precision
    mapping(uint256 => uint256) public volatilityOffsets;

    // TTL => The multiplier for volatility calculation in 1e4 precision
    mapping(uint256 => uint256) public volatilityMultipliers;

    // IV Setter addresses
    mapping(address => bool) public ivSetter;

    // xSYK Balances for each tier
    uint256[] public xSykBalances;

    // Discount for each tier
    uint256[] public discounts;

    error NotIVSetter();

    event UpdatedIVs(address sender, uint256[] ttls, uint256[] ttlIVs);

    constructor(uint256 _minOptionPricePercentage, address _xSyk) {
        minOptionPricePercentage = _minOptionPricePercentage;
        xSyk = _xSyk;

        ivSetter[msg.sender] = true;
    }

    /*---- GOVERNANCE FUNCTIONS ----*/

    /// @notice Updates the IV setter
    /// @param _setter Address of the setter
    /// @param _status Status  to set
    /// @dev Only the owner of the contract can call this function
    function updateIVSetter(address _setter, bool _status) external onlyOwner {
        ivSetter[_setter] = _status;
    }

    /// @notice Updates the implied volatility (IV) for the given time to expirations (TTLs).
    /// @param _ttls The TTLs to update the IV for.
    /// @param _ttlIVs The new IVs for the given TTLs.
    /// @dev Only the IV SETTER can call this function.
    function updateIVs(uint256[] calldata _ttls, uint256[] calldata _ttlIVs) external {
        if (!ivSetter[msg.sender]) revert NotIVSetter();

        for (uint256 i; i < _ttls.length; i++) {
            ttlToVol[_ttls[i]] = _ttlIVs[i];
        }

        emit UpdatedIVs(msg.sender, _ttls, _ttlIVs);
    }

    /// @notice updates the offset for volatility calculation
    /// @param _volatilityOffsets the new offset
    /// @param _ttls The TTLs to update the volatility offset for.
    /// @return whether offset was updated
    function updateVolatilityOffset(uint256[] calldata _volatilityOffsets, uint256[] calldata _ttls)
        external
        onlyOwner
        returns (bool)
    {
        uint256 volatilityOffsetsLength = _volatilityOffsets.length;

        for (uint256 i; i < volatilityOffsetsLength;) {
            volatilityOffsets[_ttls[i]] = _volatilityOffsets[i];

            unchecked {
                ++i;
            }
        }

        return true;
    }

    /// @notice updates the multiplier for volatility calculation
    /// @param _volatilityMultipliers the new multiplier
    /// @param _ttls The TTLs to update the volatility multiplier for.
    /// @return whether multiplier was updated
    function updateVolatilityMultiplier(uint256[] calldata _volatilityMultipliers, uint256[] calldata _ttls)
        external
        onlyOwner
        returns (bool)
    {
        for (uint256 i = 0; i < _volatilityMultipliers.length; i++) {
            volatilityMultipliers[_ttls[i]] = _volatilityMultipliers[i];
        }

        return true;
    }

    /// @notice updates % of the price of asset which is  the minimum option price possible
    /// @param _minOptionPricePercentage the new %
    /// @return whether % was updated
    function updateMinOptionPricePercentage(uint256 _minOptionPricePercentage) external onlyOwner returns (bool) {
        minOptionPricePercentage = _minOptionPricePercentage;

        return true;
    }

    /// @notice sets the xSYK balances and discounts for each tier
    /// @param _xSykBalances the xSYK balances
    /// @param _discounts the discounts
    /// @return whether the balances and discounts were set
    function setXSykBalancesAndDiscounts(uint256[] calldata _xSykBalances, uint256[] calldata _discounts)
        external
        onlyOwner
        returns (bool)
    {
        xSykBalances = _xSykBalances;
        discounts = _discounts;

        return true;
    }

    /*---- VIEWS ----*/

    /// @notice computes the option price (with liquidity multiplier)
    /// @param isPut is put option
    /// @param expiry expiry timestamp
    /// @param strike strike price
    /// @param lastPrice current price
    function getOptionPrice(bool isPut, uint256 expiry, uint256 strike, uint256 lastPrice)
        external
        view
        returns (uint256)
    {
        uint256 timeToExpiry = expiry.sub(block.timestamp).div(864);

        uint256 volatility = ttlToVol[expiry - block.timestamp];

        if (volatility == 0) revert();

        volatility = getVolatility(strike, lastPrice, volatility, expiry - block.timestamp);

        uint256 optionPrice = BlackScholes.calculate(isPut ? 1 : 0, lastPrice, strike, timeToExpiry, 0, volatility) // 0 - Put, 1 - Call
                // Number of days to expiry mul by 100
            .div(BlackScholes.DIVISOR);

        uint256 minOptionPrice = lastPrice.mul(minOptionPricePercentage).div(1e10);

        if (minOptionPrice > optionPrice) {
            return minOptionPrice;
        }

        return optionPrice;
    }

    /// @notice computes the option price (with liquidity multiplier)
    /// @param isPut is put option
    /// @param ttl time to live for the option
    /// @param strike strike price
    /// @param lastPrice current price
    function getOptionPriceViaTTL(bool isPut, uint256 ttl, uint256 strike, uint256 lastPrice)
        external
        view
        returns (uint256)
    {
        uint256 timeToExpiry = ttl.div(864);

        uint256 volatility = ttlToVol[ttl];

        if (volatility == 0) revert();

        volatility = getVolatility(strike, lastPrice, volatility, ttl);

        uint256 optionPrice = BlackScholes.calculate(isPut ? 1 : 0, lastPrice, strike, timeToExpiry, 0, volatility) // 0 - Put, 1 - Call
                // Number of days to expiry mul by 100
            .div(BlackScholes.DIVISOR);

        uint256 minOptionPrice = lastPrice.mul(minOptionPricePercentage).div(1e10);

        if (minOptionPrice > optionPrice) {
            return minOptionPrice;
        }

        return optionPrice;
    }

    /// @notice computes the volatility for a strike
    /// @param strike strike price
    /// @param lastPrice current price
    /// @param volatility volatility
    function getVolatility(uint256 strike, uint256 lastPrice, uint256 volatility, uint256 ttl)
        public
        view
        returns (uint256)
    {
        uint256 percentageDifference = strike.mul(1e2).mul(VOLATILITY_PRECISION).div(lastPrice); // 1e4 in percentage precision (1e6 is 100%)

        if (strike > lastPrice) {
            percentageDifference = percentageDifference.sub(1e6);
        } else {
            percentageDifference = uint256(1e6).sub(percentageDifference);
        }

        uint256 scaleFactor =
            volatilityOffsets[ttl] + (percentageDifference.mul(volatilityMultipliers[ttl]).div(VOLATILITY_PRECISION));

        volatility = volatility.mul(scaleFactor).div(VOLATILITY_PRECISION);

        address userAddress = tx.origin;
        uint256 tiers = xSykBalances.length;
        uint256 userDiscount = 0;
        if (tiers != 0) {
            for (uint256 i; i < tiers;) {
                uint256 balance = IERC20(xSyk).balanceOf(userAddress);
                if (balance >= xSykBalances[i]) {
                    userDiscount = discounts[i];
                } else {
                    break;
                }
                unchecked {
                    ++i;
                }
            }
        }

        volatility = volatility.mul(1e4 - userDiscount).div(1e4);

        return volatility;
    }
}

File 2 of 7 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

File 3 of 7 : BlackScholes.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

// Libraries
import {ABDKMathQuad} from "./ABDKMathQuad.sol";

/// @title Black-Scholes option pricing formula and supporting statistical functions
/// @author Dopex
/// @notice This library implements the Black-Scholes model to price options.
/// See - https://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model
/// @dev Implements the following implementation - https://cseweb.ucsd.edu/~goguen/courses/130/SayBlackScholes.html
/// Uses the ABDKMathQuad(https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMathQuad.md)
/// library to make precise calculations. It uses a DIVISOR (1e16) for maintaining precision in constants.
library BlackScholes {
    uint8 internal constant OPTION_TYPE_CALL = 0;
    uint8 internal constant OPTION_TYPE_PUT = 1;

    uint256 internal constant DIVISOR = 10 ** 16;

    /**
     * @notice The function that uses the Black-Scholes equation to calculate the option price
     * See http://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model#Black-Scholes_formula
     * NOTE: The different parts of the equation are broken down to separate functions as using
     * ABDKMathQuad makes small equations verbose.
     * @param optionType Type of option - 0 = call, 1 = put
     * @param price Stock price
     * @param strike Strike price
     * @param timeToExpiry Time to expiry in days
     * @param riskFreeRate Risk-free rate
     * @param volatility Volatility on the asset
     * @return Option price based on the Black-Scholes model
     */
    function calculate(
        uint8 optionType,
        uint256 price,
        uint256 strike,
        uint256 timeToExpiry,
        uint256 riskFreeRate,
        uint256 volatility
    ) internal pure returns (uint256) {
        bytes16 S = ABDKMathQuad.fromUInt(price);
        bytes16 X = ABDKMathQuad.fromUInt(strike);
        bytes16 T = ABDKMathQuad.div(
            ABDKMathQuad.fromUInt(timeToExpiry),
            ABDKMathQuad.fromUInt(36500) // 365 * 10 ^ DAYS_PRECISION
        );
        bytes16 r = ABDKMathQuad.div(
            ABDKMathQuad.fromUInt(riskFreeRate),
            ABDKMathQuad.fromUInt(10000)
        );
        bytes16 v = ABDKMathQuad.div(
            ABDKMathQuad.fromUInt(volatility),
            ABDKMathQuad.fromUInt(100)
        );
        bytes16 d1 = ABDKMathQuad.div(
            ABDKMathQuad.add(
                ABDKMathQuad.ln(ABDKMathQuad.div(S, X)),
                ABDKMathQuad.mul(
                    ABDKMathQuad.add(
                        r,
                        ABDKMathQuad.mul(
                            v,
                            ABDKMathQuad.div(v, ABDKMathQuad.fromUInt(2))
                        )
                    ),
                    T
                )
            ),
            ABDKMathQuad.mul(v, ABDKMathQuad.sqrt(T))
        );
        bytes16 d2 = ABDKMathQuad.sub(
            d1,
            ABDKMathQuad.mul(v, ABDKMathQuad.sqrt(T))
        );
        if (optionType == OPTION_TYPE_CALL) {
            return
                ABDKMathQuad.toUInt(
                    ABDKMathQuad.mul(
                        _calculateCallTimeDecay(S, d1, X, r, T, d2),
                        ABDKMathQuad.fromUInt(DIVISOR)
                    )
                );
        } else if (optionType == OPTION_TYPE_PUT) {
            return
                ABDKMathQuad.toUInt(
                    ABDKMathQuad.mul(
                        _calculatePutTimeDecay(X, r, T, d2, S, d1),
                        ABDKMathQuad.fromUInt(DIVISOR)
                    )
                );
        } else return 0;
    }

    /// @dev Function to caluclate the call time decay
    /// From the implementation page(https://cseweb.ucsd.edu/~goguen/courses/130/SayBlackScholes.html); part of the equation
    /// ( S * CND(d1)-X * Math.exp(-r * T) * CND(d2) );
    function _calculateCallTimeDecay(
        bytes16 S,
        bytes16 d1,
        bytes16 X,
        bytes16 r,
        bytes16 T,
        bytes16 d2
    ) internal pure returns (bytes16) {
        return
            ABDKMathQuad.sub(
                ABDKMathQuad.mul(S, CND(d1)),
                ABDKMathQuad.mul(
                    ABDKMathQuad.mul(
                        X,
                        ABDKMathQuad.exp(
                            ABDKMathQuad.mul(ABDKMathQuad.neg(r), T)
                        )
                    ),
                    CND(d2)
                )
            );
    }

    /// @dev Function to caluclate the put time decay
    /// From the implementation page(https://cseweb.ucsd.edu/~goguen/courses/130/SayBlackScholes.html); part of the equation -
    /// ( X * Math.exp(-r * T) * CND(-d2) - S * CND(-d1) );
    function _calculatePutTimeDecay(
        bytes16 X,
        bytes16 r,
        bytes16 T,
        bytes16 d2,
        bytes16 S,
        bytes16 d1
    ) internal pure returns (bytes16) {
        bytes16 price_part1 = ABDKMathQuad.mul(
            ABDKMathQuad.mul(
                X,
                ABDKMathQuad.exp(ABDKMathQuad.mul(ABDKMathQuad.neg(r), T))
            ),
            CND(ABDKMathQuad.neg(d2))
        );
        bytes16 price_part2 = ABDKMathQuad.mul(S, CND(ABDKMathQuad.neg(d1)));
        bytes16 price = ABDKMathQuad.sub(price_part1, price_part2);
        return price;
    }

    /**
     * @notice Normal cumulative distribution function.
     * See http://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_function
     * From the implementation page(https://cseweb.ucsd.edu/~goguen/courses/130/SayBlackScholes.html); part of the equation -
     * "k = 1 / (1 + .2316419 * x); return ( 1 - Math.exp(-x * x / 2)/ Math.sqrt(2*Math.PI) * k * (.31938153 + k * (-.356563782 + k * (1.781477937 + k * (-1.821255978 + k * 1.330274429)))) );"
     * NOTE: The different parts of the equation are broken down to separate functions as using
     * ABDKMathQuad makes small equations verbose.
     */
    function CND(bytes16 x) internal pure returns (bytes16) {
        if (ABDKMathQuad.toInt(x) < 0) {
            return (
                ABDKMathQuad.sub(
                    ABDKMathQuad.fromUInt(1),
                    CND(ABDKMathQuad.neg(x))
                )
            );
        } else {
            bytes16 k = ABDKMathQuad.div(
                ABDKMathQuad.fromUInt(1),
                ABDKMathQuad.add(
                    ABDKMathQuad.fromUInt(1),
                    ABDKMathQuad.mul(
                        ABDKMathQuad.div(
                            ABDKMathQuad.fromUInt(2316419000000000),
                            ABDKMathQuad.fromUInt(DIVISOR)
                        ),
                        x
                    )
                )
            );
            bytes16 CND_part2 = _getCNDPart2(k, x);
            return ABDKMathQuad.sub(ABDKMathQuad.fromUInt(1), CND_part2);
        }
    }

    function _getCNDPart2(
        bytes16 k,
        bytes16 x
    ) internal pure returns (bytes16) {
        return ABDKMathQuad.mul(_getCNDPart2_1(x), _getCNDPart2_2(k));
    }

    function _getCNDPart2_1(bytes16 x) internal pure returns (bytes16) {
        return
            ABDKMathQuad.div(
                ABDKMathQuad.exp(
                    ABDKMathQuad.mul(
                        ABDKMathQuad.neg(x),
                        ABDKMathQuad.div(x, ABDKMathQuad.fromUInt(2))
                    )
                ),
                ABDKMathQuad.sqrt(
                    ABDKMathQuad.mul(
                        ABDKMathQuad.fromUInt(2),
                        ABDKMathQuad.div(
                            ABDKMathQuad.fromUInt(31415926530000000),
                            ABDKMathQuad.fromUInt(DIVISOR)
                        )
                    )
                )
            );
    }

    function _getCNDPart2_2(bytes16 k) internal pure returns (bytes16) {
        return
            ABDKMathQuad.mul(
                ABDKMathQuad.add(
                    ABDKMathQuad.div(
                        ABDKMathQuad.fromUInt(3193815300000000),
                        ABDKMathQuad.fromUInt(DIVISOR)
                    ),
                    ABDKMathQuad.mul(
                        k,
                        ABDKMathQuad.add(
                            ABDKMathQuad.neg(
                                ABDKMathQuad.div(
                                    ABDKMathQuad.fromUInt(3565637820000000),
                                    ABDKMathQuad.fromUInt(DIVISOR)
                                )
                            ),
                            ABDKMathQuad.mul(
                                k,
                                ABDKMathQuad.add(
                                    ABDKMathQuad.div(
                                        ABDKMathQuad.fromUInt(
                                            17814779370000000
                                        ),
                                        ABDKMathQuad.fromUInt(DIVISOR)
                                    ),
                                    _getCNDPart2_2_1(k)
                                )
                            )
                        )
                    )
                ),
                k
            );
    }

    function _getCNDPart2_2_1(bytes16 k) internal pure returns (bytes16) {
        return
            ABDKMathQuad.mul(
                k,
                ABDKMathQuad.add(
                    ABDKMathQuad.neg(
                        ABDKMathQuad.div(
                            ABDKMathQuad.fromUInt(18212559780000000),
                            ABDKMathQuad.fromUInt(DIVISOR)
                        )
                    ),
                    ABDKMathQuad.mul(
                        k,
                        ABDKMathQuad.div(
                            ABDKMathQuad.fromUInt(13302744290000000),
                            ABDKMathQuad.fromUInt(DIVISOR)
                        )
                    )
                )
            );
    }
}

File 4 of 7 : 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.8.13;

/**
 * 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) {
        unchecked {
            if (x == 0) return bytes16(0);
            else {
                // We rely on overflow behavior here
                uint256 result = uint256(x > 0 ? x : -x);

                uint256 msb = mostSignificantBit(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) {
        unchecked {
            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) {
        unchecked {
            if (x == 0) return bytes16(0);
            else {
                uint256 result = x;

                uint256 msb = mostSignificantBit(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) {
        unchecked {
            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) {
        unchecked {
            if (x == 0) return bytes16(0);
            else {
                // We rely on overflow behavior here
                uint256 result = uint256(x > 0 ? x : -x);

                uint256 msb = mostSignificantBit(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) {
        unchecked {
            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) {
        unchecked {
            if (x == 0) return bytes16(0);
            else {
                // We rely on overflow behavior here
                uint256 result = uint128(x > 0 ? x : -x);

                uint256 msb = mostSignificantBit(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) {
        unchecked {
            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(int256(result)); // We rely on overflow behavior here
            } else {
                require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
                return int128(int256(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) {
        unchecked {
            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) {
        unchecked {
            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 = mostSignificantBit(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) {
        unchecked {
            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 = mostSignificantBit(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) {
        unchecked {
            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) {
        unchecked {
            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) {
        unchecked {
            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) {
        unchecked {
            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) {
        unchecked {
            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) {
        unchecked {
            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) {
        unchecked {
            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 = mostSignificantBit(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) {
        unchecked {
            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) {
        unchecked {
            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
                    : mostSignificantBit(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) {
        unchecked {
            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) {
                        uint256 shift = 226 - mostSignificantBit(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
                    ? mostSignificantBit(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) {
        unchecked {
            return x ^ 0x80000000000000000000000000000000;
        }
    }

    /**
     * Calculate |x|.
     *
     * @param x quadruple precision number
     * @return quadruple precision number
     */
    function abs(bytes16 x) internal pure returns (bytes16) {
        unchecked {
            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) {
        unchecked {
            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 = mostSignificantBit(xSignifier);
                            uint256 shift = (226 - msb) & 0xFE;
                            xSignifier <<= shift;
                            xExponent -= (shift - 112) >> 1;
                        }
                    } else {
                        if (xSignifier >= 0x10000000000000000000000000000)
                            xSignifier <<= 112;
                        else {
                            uint256 msb = mostSignificantBit(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) {
        unchecked {
            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 = mostSignificantBit(xSignifier);
                            resultSignifier = 16493 - msb;
                            xSignifier <<= 127 - msb;
                        }
                    }

                    if (xSignifier == 0x80000000000000000000000000000000) {
                        if (resultNegative) resultSignifier += 1;
                        uint256 shift = 112 -
                            mostSignificantBit(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) {
        unchecked {
            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) {
        unchecked {
            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) {
        unchecked {
            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 mostSignificantBit(uint256 x) private pure returns (uint256) {
        unchecked {
            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;
        }
    }
}

File 5 of 7 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 6 of 7 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "v3-core/=lib/v3-core/",
    "v3-periphery/=lib/v3-periphery/contracts/",
    "@uniswap/v3-core/=lib/v3-core/",
    "base64-sol/=lib/openzeppelin-contracts/contracts/utils/",
    "BokkyPooBahsDateTimeLibrary/=lib/BokkyPooBahsDateTimeLibrary/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 0
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_minOptionPricePercentage","type":"uint256"},{"internalType":"address","name":"_xSyk","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotIVSetter","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ttls","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"ttlIVs","type":"uint256[]"}],"name":"UpdatedIVs","type":"event"},{"inputs":[],"name":"VOLATILITY_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"discounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isPut","type":"bool"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"strike","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"}],"name":"getOptionPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isPut","type":"bool"},{"internalType":"uint256","name":"ttl","type":"uint256"},{"internalType":"uint256","name":"strike","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"}],"name":"getOptionPriceViaTTL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"strike","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"},{"internalType":"uint256","name":"ttl","type":"uint256"}],"name":"getVolatility","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ivSetter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minOptionPricePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_xSykBalances","type":"uint256[]"},{"internalType":"uint256[]","name":"_discounts","type":"uint256[]"}],"name":"setXSykBalancesAndDiscounts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ttlToVol","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_setter","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"updateIVSetter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ttls","type":"uint256[]"},{"internalType":"uint256[]","name":"_ttlIVs","type":"uint256[]"}],"name":"updateIVs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minOptionPricePercentage","type":"uint256"}],"name":"updateMinOptionPricePercentage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_volatilityMultipliers","type":"uint256[]"},{"internalType":"uint256[]","name":"_ttls","type":"uint256[]"}],"name":"updateVolatilityMultiplier","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_volatilityOffsets","type":"uint256[]"},{"internalType":"uint256[]","name":"_ttls","type":"uint256[]"}],"name":"updateVolatilityOffset","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"volatilityMultipliers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"volatilityOffsets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xSyk","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xSykBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101075760003560e01c8063016d47b51461010c57806307c91935146101215780631ce2a6881461014757806325b2a93b1461015a5780632ae0d14114610163578063326611f814610176578063427ec698146101995780634a95155c146101b95780635b7f6d77146101cc578063715018a6146101df578063717a1dec146101e75780637b0bfdbb146102075780637c90d3c71461021a5780638da5cb5b14610223578063aaa534da14610238578063b12ce0b41461024b578063bae6a6901461026b578063cf24eb241461027e578063d1dfc6b314610291578063d5f1b2ce146102a4578063f2fde38b146102c7575b600080fd5b61011f61011a366004612da0565b6102da565b005b61013461012f366004612e0b565b6103b6565b6040519081526020015b60405180910390f35b610134610155366004612e34565b6103d7565b61013460015481565b61011f610171366004612e84565b610487565b610189610184366004612e0b565b6104ba565b604051901515815260200161013e565b6101346101a7366004612e0b565b60046020526000908152604090205481565b6101896101c7366004612da0565b6104d0565b6101346101da366004612e34565b6104ff565b61011f610551565b6101346101f5366004612e0b565b60056020526000908152604090205481565b610189610215366004612da0565b610565565b61013461271081565b61022b6105d5565b60405161013e9190612eb7565b610134610246366004612ecb565b6105e4565b610134610259366004612e0b565b60036020526000908152604090205481565b610134610279366004612e0b565b61078e565b60025461022b906001600160a01b031681565b61018961029f366004612da0565b61079e565b6101896102b2366004612efd565b60066020526000908152604090205460ff1681565b61011f6102d5366004612efd565b610812565b3360009081526006602052604090205460ff1661030a5760405163f25c884f60e01b815260040160405180910390fd5b60005b838110156103705782828281811061032757610327612f18565b905060200201356003600087878581811061034457610344612f18565b90506020020135815260200190815260200160002081905550808061036890612f44565b91505061030d565b507f95805653338d965e92ffa53d6faff39c28f90a2e8a5166c48e94ca9a919f424533858585856040516103a8959493929190612f93565b60405180910390a150505050565b600781815481106103c657600080fd5b600091825260209091200154905081565b6000806103e685610360610890565b60008681526003602052604081205491925081900361040457600080fd5b610410858583896105e4565b90506000610442662386f26fc1000061043c8a61042e576000610431565b60015b888a886000896108a5565b90610890565b905060006104646402540be40061043c600154896109f690919063ffffffff16565b90508181111561047957935061047f92505050565b50925050505b949350505050565b61048f610a02565b6001600160a01b03919091166000908152600660205260409020805460ff1916911515919091179055565b60006104c4610a02565b5060018181555b919050565b60006104da610a02565b6104e660078686612cf5565b506104f360088484612cf5565b50600195945050505050565b60008061051261036061043c8742610a61565b905060006003816105234289612fd7565b81526020019081526020016000205490508060000361054157600080fd5b610410858583610246428b612fd7565b610559610a02565b6105636000610a6d565b565b600061056f610a02565b60005b848110156104f35785858281811061058c5761058c612f18565b90506020020135600560008686858181106105a9576105a9612f18565b9050602002013581526020019081526020016000208190555080806105cd90612f44565b915050610572565b6000546001600160a01b031690565b6000806106028561043c6127106105fc8a60646109f6565b906109f6565b9050848611156106205761061981620f4240610a61565b9050610630565b61062d620f424082610a61565b90505b600083815260056020526040812054610652906127109061043c9085906109f6565b60008581526004602052604090205461066b9190612fee565b905061067d61271061043c87846109f6565b6007549095503290600081156107665760005b82811015610764576002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906106c9908890600401612eb7565b602060405180830381865afa1580156106e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070a9190613006565b90506007828154811061071f5761071f612f18565b90600052602060002001548110610755576008828154811061074357610743612f18565b9060005260206000200154925061075b565b50610764565b50600101610690565b505b61078061271061043c6107798483612fd7565b8b906109f6565b9a9950505050505050505050565b600881815481106103c657600080fd5b60006107a8610a02565b8360005b81811015610805578686828181106107c6576107c6612f18565b90506020020135600460008787858181106107e3576107e3612f18565b60209081029290920135835250810191909152604001600020556001016107ac565b5060019695505050505050565b61081a610a02565b6001600160a01b0381166108845760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61088d81610a6d565b50565b600061089c8284613035565b90505b92915050565b6000806108b187610abd565b905060006108be87610abd565b905060006108de6108ce88610abd565b6108d9618e94610abd565b610b24565b905060006108f96108ee88610abd565b6108d9612710610abd565b9050600061091361090988610abd565b6108d96064610abd565b9050600061096561095861092f61092a8989610b24565b610de4565b61094d6109528761094d886109488a6108d96002610abd565b610e07565b611070565b88610e07565b6108d9846109488861143a565b9050600061097f8261097a856109488961143a565b611613565b905060ff8e166109c0576109b26109ad61099d89858a898b88611625565b610948662386f26fc10000610abd565b61166c565b9750505050505050506109ec565b60001960ff8f16016109e0576109b26109ad61099d888789868d896116f0565b60009750505050505050505b9695505050505050565b600061089c8284613057565b33610a0b6105d5565b6001600160a01b0316146105635760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161087b565b600061089c8284612fd7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600081600003610acf57506000919050565b816000610adb82611742565b90506070811015610af4578060700382901b9150610b07565b6070811115610b07576070810382901c91505b613fff0160701b6001600160701b03919091161760801b92915050565b6000617fff60f084811c8216919084901c811690829003610b695780617fff03610b58575061ffff60ef1b915061089f9050565b505050600160ff1b8116821861089f565b80617fff03610ba557600160801b600160f01b03841615610b94575061ffff60ef1b915061089f9050565b505050808218600160ff1b1661089f565b600160801b600160ff1b038416600003610bf557600160801b600160ff1b038516600003610bdd575061ffff60ef1b915061089f9050565b505050808218600160ff1b16617fff60f01b1761089f565b6001600160701b03608085901c166000829003610c155760019150610c1c565b600160701b175b6001600160701b03608087901c166000849003610c5f578015610c5a576000610c4482611742565b6001955060e20393840160711901939190911b90505b610c69565b600160701b1760721b5b818181610c7857610c7861301f565b04905080600003610ca857600160ff1b87871816610c97576000610c9d565b600160ff1b5b94505050505061089f565b6001606c1b811015610cbc57610cbc613076565b6000600160731b821015610cfb57600160721b821015610cf057600160711b821015610ce9576070610cf3565b6071610cf3565b60725b60ff16610d04565b610d0482611742565b905083614071018186011115610d2257617fff945060009150610db5565b83818601613ffc011015610d3d576000945060009150610db5565b83818601613f8c011015610d8a578385613ffc011115610d68578385613ffc010382901b9150610d81565b8385613ffc011015610d8157613ffc8585030382901c91505b60009450610db5565b6070811115610d9d576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b9550505050505061089f565b600061089f610df2836117df565b6f3ffe62e42fefa39ef35793c7673007e560801b5b6000617fff60f084811c8216919084901c811690829003610ea65780617fff03610e82576001600160801b031980851690861603610e5057505050600160ff1b8116821861089f565b6001600160801b031985851816600160ff1b03610e725750505081811761089f565b5061ffff60ef1b915061089f9050565b600160801b600160ff1b038416600003610b58575061ffff60ef1b915061089f9050565b80617fff03610ee457600160801b600160ff1b038516600003610ed3575061ffff60ef1b915061089f9050565b505050600160ff1b8216811861089f565b6001600160701b03608086901c166000839003610f045760019250610f0b565b600160701b175b6001600160701b03608086901c166000839003610f2b5760019250610f32565b600160701b175b808202915081600003610f5357600160ff1b87871816610c97576000610c9d565b928201926000600160e11b831015610f8657600160e01b831015610f7f57610f7a83611742565b610f89565b60e0610f89565b60e15b90506140708186011015610fa4576000945060009250611041565b6140e08186011015610fe757614070851015610fc957846140700383901c9250610fde565b614070851115610fde57614070850383901b92505b60009450611041565b61c0dd818601111561100157617fff945060009250611041565b6070811115611018576070810383901c925061102b565b607081101561102b578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b9550505050505061089f565b6000617fff60f084811c8216919084901c8116908290036110bc5780617fff036110b2576001600160801b031980851690861603610e7257849250505061089f565b849250505061089f565b80617fff036110cf57839250505061089f565b6001607f1b608086901c90811015906001600160701b031660008490036110f95760019350611100565b600160701b175b6001607f1b608087901c90811015906001600160701b0316600085900361112a5760019450611131565b600160701b175b82600003611164576001600160801b03198816600160ff1b146111545787611157565b60005b965050505050505061089f565b80600003611187576001600160801b03198916600160ff1b146111545788611157565b848603821515851515036112905760708113156111ad578997505050505050505061089f565b60008113156111bf5790811c906111ee565b606f198112156111d8578897505050505050505061089f565b60008112156111ee578060000384901c93508596505b92810192600160711b8410611209576001968701969390931c925b86617fff0361123a578461122257617fff60f01b61122c565b6001600160f01b03195b97505050505050505061089f565b600160701b84101561124f576000965061125c565b6001600160701b03841693505b83607088901b8661126e576000611274565b6001607f1b5b6001600160801b0316171760801b97505050505050505061089f565b60008113156112ab57600184901b93506001870396506112c2565b60008112156112c257600182901b91506001860396505b60708113156112d45760019150611321565b60018113156112f1576001810360018303901c6001019150611321565b606f198112156113045760019350611321565b600019811215611321576001816000030360018503901c60010193505b81841061133257818403935061133b565b83820393508294505b8360000361135457506000965061089f95505050505050565b600061135f85611742565b90508060710361138457600185901c6001600160701b031694506001880197506113d3565b60708110156113c6576070819003808911156113b3578086901b6001600160701b0316955080890398506113c0565b600098600019019590951b945b506113d3565b6001600160701b03851694505b87617fff0361140557856113ec57617fff60f01b6113f6565b6001600160f01b03195b9850505050505050505061089f565b84607089901b8761141757600061141d565b6001607f1b5b6001600160801b0316171760801b9850505050505050505061089f565b60006001607f1b608083901c1115611458575061ffff60ef1b919050565b617fff60f083901c811690819003611471575090919050565b6001600160701b03608084901c1660008290036114915760019150611498565b600160701b175b806000036114aa575060009392505050565b613fff8201600190811c92161580156114fc57600160701b82106114d457607182901b9150611537565b60006114df83611742565b60e20360fe16606f19810160011c909403939290921b9150611537565b600160701b821061151357607082901b9150611537565b600061151e83611742565b60e10360fe16606f19810160011c909403939290921b91505b600160701b80830401600190811c908184816115555761155561301f565b048201901c9050600181848161156d5761156d61301f565b048201901c905060018184816115855761158561301f565b048201901c9050600181848161159d5761159d61301f565b048201901c905060018184816115b5576115b561301f565b048201901c905060018184816115cd576115cd61301f565b048201901c905060008184816115e5576115e561301f565b049050818110156115f4578091505b816001600160701b0316607086901b1760801b95505050505050919050565b600061089c83600160ff1b8418611070565b60006116616116378861094889611997565b61097a6116588861094861165361164d8b611a27565b8a610e07565b611a30565b61094886611997565b979650505050505050565b6000617fff60f083901c16613fff81101561168a5750600092915050565b6001607f1b608084901c1061169e57600080fd5b6140fe8111156116ad57600080fd5b600160701b6001600160701b03608085901c161761406f8210156116d75761406f8290031c6116e9565b61406f8211156116e95761406e1982011b5b9392505050565b60008061172061170f896109486116536117098c611a27565b8b610e07565b61094861171b88611a27565b611997565b905060006117348561094861171b87611a27565b905060006107808383611613565b600080821161175057600080fd5b6000600160801b831061176557608092831c92015b600160401b831061177857604092831c92015b600160201b831061178b57602092831c92015b62010000831061179d57601092831c92015b61010083106117ae57600892831c92015b601083106117be57600492831c92015b600483106117ce57600292831c92015b6002831061089f5760010192915050565b60006001607f1b608083901c11156117fd575061ffff60ef1b919050565b6001600160801b03198216613fff60f01b0361181b57506000919050565b617fff60f083901c811690819003611834575090919050565b6001600160701b03608084901c166000829003611854576001915061185b565b600160701b175b8060000361187457506001600160f01b03199392505050565b600061406f81613fff851061189a5750600f9290921b9160009150613ffe1984016118d9565b60019250600160701b84106118bc5784613ffe039050600f84901b93506118d9565b60006118c785611742565b607f8190039590951b9461406d039150505b836001607f1b0361190f5782156118ee576001015b60006118f982611742565b60700390508082901b915080830392505061195d565b60008361191d576000611920565b60015b60ff1690505b600160701b82101561195b5793800260ff81901c607f81019190911c94600019939093019260019290921b9082180190611926565b505b806001600160701b0316607083901b8461197857600061197e565b6001607f1b5b6001600160801b0316171760801b979650505050505050565b6000806119a383611a57565b12156119c25761089f6119b66001610abd565b61097a61171b85611a27565b6000611a046119d16001610abd565b6108d96119de6001610abd565b61094d6109526119f466083ac553a55e00610abd565b6108d9662386f26fc10000610abd565b90506000611a128285611afe565b905061047f611a216001610abd565b82611613565b600160ff1b1890565b600061089f611a52836f1fffb8aa3b295c17f0bbbe87fed0691d60811b610e07565b611b15565b6000617fff60f083901c166140fe811115611a7157600080fd5b613fff811015611a845750600092915050565b600160701b6001600160701b03608085901c161761406f821015611aae5761406f8290031c611ac0565b61406f821115611ac05761406e1982011b5b6001607f1b608085901c10611aea57600160ff1b811115611ae057600080fd5b6000039392505050565b6001600160ff1b038111156116e957600080fd5b600061089c611b0c83612c0f565b61094885612c59565b60006001607f1b608083901c90811190617fff60f085901c8116916001600160701b03169082148015611b4757508015155b15611b5b575061ffff60ef1b949350505050565b61400d821115611b815782611b7557617fff60f01b611b78565b60005b95945050505050565b613f7f821015611b9a5750613fff60f01b949350505050565b81600003611bab5760019150611bb2565b600160701b175b613fef821115611bc857613fee1982011b611bda565b613fef821015611bda57613fef8290031c5b828015611beb575061203760811b81115b15611bfb57506000949350505050565b82158015611c0f575060016001608e1b0381115b15611c235750617fff60f01b949350505050565b6001600160801b0381169060801c838015611c3d57508115155b15611c49579019906001015b6001607f1b82811615611c6d5770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6001607e1b831615611c90577001306fe0a31b7152de8d5a46305c85edec0260801c5b6001607d1b831615611cb3577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6001607c1b831615611cd65770010b5586cf9890f6298b92b71842a983630260801c5b6001607b1b831615611cf9577001059b0d31585743ae7c548eb68ca417fd0260801c5b6001607a1b831615611d1c57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b600160791b831615611d3f5770010163da9fb33356d84a66ae336dcdfa3f0260801c5b600160781b831615611d6257700100b1afa5abcbed6129ab13ec11dc95430260801c5b600160771b831615611d855770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600160761b831615611da8577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600160751b831615611dcb57700100162f3904051fa128bca9c55c31e5df0260801c5b600160741b831615611dee577001000b175effdc76ba38e31671ca9397250260801c5b600160731b831615611e1157700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600160721b831615611e345770010002c5cc37da9491d0985c348c68e7b30260801c5b600160711b831615611e57577001000162e525ee054754457d59952920260260801c5b600160701b831615611e7a5770010000b17255775c040618bf4a4ade83fc0260801c5b6001606f1b831615611e9d577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6001606e1b831615611ec057700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6001606d1b831615611ee35770010000162e43f4f831060e02d839a9d16d0260801c5b6001606c1b831615611f0657700100000b1721bcfc99d9f890ea069117630260801c5b6001606b1b831615611f295770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6001606a1b831615611f4c577001000002c5c863b73f016468f6bac5ca2b0260801c5b600160691b831615611f6f57700100000162e430e5a18f6119e3c02282a50260801c5b600160681b831615611f92577001000000b1721835514b86e6d96efd1bfe0260801c5b600160671b831615611fb557700100000058b90c0b48c6be5df846c5b2ef0260801c5b600160661b831615611fd85770010000002c5c8601cc6b9e94213c72737a0260801c5b600160651b831615611ffb577001000000162e42fff037df38aa2b219f060260801c5b600160641b83161561201e5770010000000b17217fba9c739aa5819f44f90260801c5b600160631b831615612041577001000000058b90bfcdee5acd3c1cedc8230260801c5b600160621b83161561206457700100000002c5c85fe31f35a6a30da1be500260801c5b600160611b8316156120875770010000000162e42ff0999ce3541b9fffcf0260801c5b600160601b8316156120aa57700100000000b17217f80f4ef5aadda455540260801c5b6001605f1b8316156120cd5770010000000058b90bfbf8479bd5a81b51ad0260801c5b6001605e1b8316156120f0577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6001605d1b83161561211357700100000000162e42fefb2fed257559bdaa0260801c5b6001605c1b831615612136577001000000000b17217f7d5a7716bba4a9ae0260801c5b6001605b1b83161561215957700100000000058b90bfbe9ddbac5e109cce0260801c5b6001605a1b83161561217c5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600160591b83161561219f577001000000000162e42fefa494f1478fde050260801c5b600160581b8316156121c25770010000000000b17217f7d20cf927c8e94c0260801c5b600160571b8316156121e5577001000000000058b90bfbe8f71cb4e4b33d0260801c5b600160561b83161561220857700100000000002c5c85fdf477b662b269450260801c5b600160551b83161561222b5770010000000000162e42fefa3ae53369388c0260801c5b600160541b83161561224e57700100000000000b17217f7d1d351a389d400260801c5b600160531b8316156122715770010000000000058b90bfbe8e8b2d3d4ede0260801c5b600160521b831615612294577001000000000002c5c85fdf4741bea6e77e0260801c5b600160511b8316156122b757700100000000000162e42fefa39fe95583c20260801c5b600160501b8316156122d95769b17217f7d1cfb72b45e1600160801b010260801c5b6001604f1b8316156122fb576958b90bfbe8e7cc35c3f0600160801b010260801c5b6001604e1b83161561231d57692c5c85fdf473e242ea38600160801b010260801c5b6001604d1b83161561233f5769162e42fefa39f02b772c600160801b010260801c5b6001604c1b83161561236157690b17217f7d1cf7d83c1a600160801b010260801c5b6001604b1b8316156123835769058b90bfbe8e7bdcbe2e600160801b010260801c5b6001604a1b8316156123a5576902c5c85fdf473dea871f600160801b010260801c5b600160491b8316156123c757690162e42fefa39ef44d91600160801b010260801c5b600160481b8316156123e85768b17217f7d1cf79e949600160801b010260801c5b600160471b831615612409576858b90bfbe8e7bce544600160801b010260801c5b600160461b83161561242a57682c5c85fdf473de6eca600160801b010260801c5b600160451b83161561244b5768162e42fefa39ef366f600160801b010260801c5b600160441b83161561246c57680b17217f7d1cf79afa600160801b010260801c5b600160431b83161561248d5768058b90bfbe8e7bcd6d600160801b010260801c5b600160421b8316156124ae576802c5c85fdf473de6b2600160801b010260801c5b600160411b8316156124cf57680162e42fefa39ef358600160801b010260801c5b600160401b8316156124ef5767b17217f7d1cf79ab600160801b010260801c5b6001603f1b83161561250f576758b90bfbe8e7bcd5600160801b010260801c5b6001603e1b83161561252f57672c5c85fdf473de6a600160801b010260801c5b6001603d1b83161561254f5767162e42fefa39ef34600160801b010260801c5b6001603c1b83161561256f57670b17217f7d1cf799600160801b010260801c5b6001603b1b83161561258f5767058b90bfbe8e7bcc600160801b010260801c5b6001603a1b8316156125af576702c5c85fdf473de5600160801b010260801c5b600160391b8316156125cf57670162e42fefa39ef2600160801b010260801c5b600160381b8316156125ee5766b17217f7d1cf78600160801b010260801c5b600160371b83161561260d576658b90bfbe8e7bb600160801b010260801c5b600160361b83161561262c57662c5c85fdf473dd600160801b010260801c5b600160351b83161561264b5766162e42fefa39ee600160801b010260801c5b600160341b83161561266a57660b17217f7d1cf6600160801b010260801c5b600160331b8316156126895766058b90bfbe8e7a600160801b010260801c5b600160321b8316156126a8576602c5c85fdf473c600160801b010260801c5b600160311b8316156126c757660162e42fefa39d600160801b010260801c5b600160301b8316156126e55765b17217f7d1ce600160801b010260801c5b6001602f1b831615612703576558b90bfbe8e6600160801b010260801c5b6001602e1b83161561272157652c5c85fdf472600160801b010260801c5b6001602d1b83161561273f5765162e42fefa38600160801b010260801c5b6001602c1b83161561275d57650b17217f7d1b600160801b010260801c5b6001602b1b83161561277b5765058b90bfbe8d600160801b010260801c5b6001602a1b831615612799576502c5c85fdf46600160801b010260801c5b600160291b8316156127b757650162e42fefa2600160801b010260801c5b600160281b8316156127d45764b17217f7d0600160801b010260801c5b600160271b8316156127f1576458b90bfbe7600160801b010260801c5b600160261b83161561280e57642c5c85fdf3600160801b010260801c5b600160251b83161561282b5764162e42fef9600160801b010260801c5b600160241b83161561284857640b17217f7c600160801b010260801c5b600160231b8316156128655764058b90bfbd600160801b010260801c5b600160221b831615612882576402c5c85fde600160801b010260801c5b600160211b83161561289f57640162e42fee600160801b010260801c5b600160201b8316156128bb5763b17217f6600160801b010260801c5b63800000008316156128d7576358b90bfa600160801b010260801c5b63400000008316156128f357632c5c85fc600160801b010260801c5b632000000083161561290f5763162e42fd600160801b010260801c5b631000000083161561292b57630b17217e600160801b010260801c5b63080000008316156129475763058b90be600160801b010260801c5b6304000000831615612963576302c5c85e600160801b010260801c5b630200000083161561297f57630162e42e600160801b010260801c5b630100000083161561299a5762b17216600160801b010260801c5b628000008316156129b4576258b90a600160801b010260801c5b624000008316156129ce57622c5c84600160801b010260801c5b622000008316156129e85762162e41600160801b010260801c5b62100000831615612a0257620b1720600160801b010260801c5b62080000831615612a1c5762058b8f600160801b010260801c5b62040000831615612a36576202c5c7600160801b010260801c5b62020000831615612a5057620162e3600160801b010260801c5b62010000831615612a695761b171600160801b010260801c5b618000831615612a81576158b8600160801b010260801c5b614000831615612a9957612c5b600160801b010260801c5b612000831615612ab15761162d600160801b010260801c5b611000831615612ac957610b16600160801b010260801c5b610800831615612ae15761058a600160801b010260801c5b610400831615612af9576102c4600160801b010260801c5b610200831615612b1157610161600160801b010260801c5b610100831615612b285760b0600160801b010260801c5b6080831615612b3e576057600160801b010260801c5b6040831615612b5457602b600160801b010260801c5b6020831615612b6a576015600160801b010260801c5b6010831615612b8057600a600160801b010260801c5b6008831615612b96576004600160801b010260801c5b6004831615612bac576001600160801b010260801c5b84612bcd57600f81901c6001600160701b03169050613fff82019150612bfc565b613ffe8211612bf257600f81901c6001600160701b0316905081613fff039150612bfc565b600091613fee19011c5b60709190911b1760801b95945050505050565b600061089f612c31611653612c2385611a27565b610948866108d96002610abd565b6108d9612c54612c416002610abd565b6109486119f4666f9c9e651c4480610abd565b61143a565b600061089f612cb9612c746119f4660b58c2126f4900610abd565b61094d85610948612c96612c916119f4660caaedbfa8a700610abd565b611a27565b61094d89610948612cb06119f4663f4a728c19ce80610abd565b61094d8d612cbf565b83610e07565b600061089f82610948612cde612c916119f46640b43a04233100610abd565b61094d866109486119f4662f42c683f17c80610abd565b828054828255906000526020600020908101928215612d30579160200282015b82811115612d30578235825591602001919060010190612d15565b50612d3c929150612d40565b5090565b5b80821115612d3c5760008155600101612d41565b60008083601f840112612d6757600080fd5b5081356001600160401b03811115612d7e57600080fd5b6020830191508360208260051b8501011115612d9957600080fd5b9250929050565b60008060008060408587031215612db657600080fd5b84356001600160401b0380821115612dcd57600080fd5b612dd988838901612d55565b90965094506020870135915080821115612df257600080fd5b50612dff87828801612d55565b95989497509550505050565b600060208284031215612e1d57600080fd5b5035919050565b803580151581146104cb57600080fd5b60008060008060808587031215612e4a57600080fd5b612e5385612e24565b966020860135965060408601359560600135945092505050565b80356001600160a01b03811681146104cb57600080fd5b60008060408385031215612e9757600080fd5b612ea083612e6d565b9150612eae60208401612e24565b90509250929050565b6001600160a01b0391909116815260200190565b60008060008060808587031215612ee157600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215612f0f57600080fd5b61089c82612e6d565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612f5657612f56612f2e565b5060010190565b81835260006001600160fb1b03831115612f7657600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b0386168152606060208201819052600090612fb89083018688612f5d565b8281036040840152612fcb818587612f5d565b98975050505050505050565b600082821015612fe957612fe9612f2e565b500390565b6000821982111561300157613001612f2e565b500190565b60006020828403121561301857600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b60008261305257634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561307157613071612f2e565b500290565b634e487b7160e01b600052600160045260246000fdfea264697066735822122064bc6f460f65931cebf50c2a6e57d0d2cc0fa236481e9dcc45f2a93d0038f0cb64736f6c634300080f0033

Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

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

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