Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
OptionPricingLinearV2
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; // Libraries import {SafeMath} from "../../../libraries/math/SafeMath.sol"; import {BlackScholes} from "./external/BlackScholes.sol"; // Contracts import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol"; contract OptionPricingLinearV2 is Ownable { using SafeMath for uint256; // The offset for volatility calculation in 1e4 precision uint256 public volatilityOffset; // The multiplier for volatility calculation in 1e4 precision uint256 public volatilityMultiplier; // 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; // Time to expiry => volatility mapping(uint256 => uint256) public ttlToVol; // IV Setter addresses mapping(address => bool) public ivSetter; error NotIVSetter(); error Vol_Not_Set(); error ArrayLengthMismatch(); constructor(uint256 _volatilityOffset, uint256 _volatilityMultiplier, uint256 _minOptionPricePercentage) Ownable(msg.sender) { volatilityOffset = _volatilityOffset; volatilityMultiplier = _volatilityMultiplier; minOptionPricePercentage = _minOptionPricePercentage; 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 _ttlIV The new IVs for the given TTLs. /// @dev Only the IV SETTER can call this function. function updateIVs(uint256[] calldata _ttls, uint256[] calldata _ttlIV) external { if (!ivSetter[msg.sender]) revert NotIVSetter(); if (_ttls.length != _ttlIV.length) revert ArrayLengthMismatch(); for (uint256 i; i < _ttls.length; i++) { ttlToVol[_ttls[i]] = _ttlIV[i]; } } /// @notice updates the offset for volatility calculation /// @param _volatilityOffset the new offset /// @return whether offset was updated function updateVolatilityOffset(uint256 _volatilityOffset) external onlyOwner returns (bool) { volatilityOffset = _volatilityOffset; return true; } /// @notice updates the multiplier for volatility calculation /// @param _volatilityMultiplier the new multiplier /// @return whether multiplier was updated function updateVolatilityMultiplier(uint256 _volatilityMultiplier) external onlyOwner returns (bool) { volatilityMultiplier = _volatilityMultiplier; 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; } /*---- VIEWS ----*/ /// @notice computes the option price (with liquidity multiplier) /// @param hook the address of the hook /// @param isPut is put option /// @param expiry expiry timestamp /// @param strike strike price /// @param lastPrice current price function getOptionPrice(address hook, bool isPut, uint256 expiry, uint256 ttl, uint256 strike, uint256 lastPrice) external view returns (uint256) { uint256 timeToExpiry = expiry.sub(block.timestamp).div(864); uint256 volatility = ttlToVol[ttl]; if (volatility == 0) revert Vol_Not_Set(); volatility = getVolatility(strike, lastPrice, volatility); 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 hook the address of the hook /// @param isPut is put option /// @param ttl time to live for the option /// @param strike strike price /// @param lastPrice current price function getOptionPriceViaTTL(address hook, 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); 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) 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 = volatilityOffset + (percentageDifference.mul(volatilityMultiplier).div(VOLATILITY_PRECISION)); return (volatility.mul(scaleFactor).div(VOLATILITY_PRECISION)); } }
pragma solidity ^0.8.13; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { if (a == 0) { return 0; } c = a * b; assert(c / a == b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 // uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return a / b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } }
// 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)) ) ) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../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. * * The initial owner is set to the address provided by the deployer. 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; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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 { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _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); } }
// 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; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts/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/", "v3-core/=lib/v3-core/contracts/", "v3-periphery/=lib/v3-periphery/contracts/", "@uniswap/v3-core/=lib/v3-core/", "@uniswap/v3-periphery/=lib/v3-periphery/", "@openzeppelin/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"_volatilityOffset","type":"uint256"},{"internalType":"uint256","name":"_volatilityMultiplier","type":"uint256"},{"internalType":"uint256","name":"_minOptionPricePercentage","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"NotIVSetter","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"Vol_Not_Set","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"},{"inputs":[],"name":"VOLATILITY_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hook","type":"address"},{"internalType":"bool","name":"isPut","type":"bool"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"ttl","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":"address","name":"hook","type":"address"},{"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"}],"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":"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":"_ttlIV","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":"_volatilityMultiplier","type":"uint256"}],"name":"updateVolatilityMultiplier","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_volatilityOffset","type":"uint256"}],"name":"updateVolatilityOffset","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"volatilityMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"volatilityOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b5060405161300438038061300483398101604081905261002e916100d8565b338061005357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61005c81610089565b506001928355600291909155600355335f908152600560205260409020805460ff19169091179055610103565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f805f606084860312156100ea575f80fd5b5050815160208301516040909301519094929350919050565b612ef4806101105f395ff3fe608060405234801561000f575f80fd5b5060043610610106575f3560e01c80638da5cb5b1161009e578063c83ffad21161006e578063c83ffad2146101fd578063d5f1b2ce14610210578063d82940a314610232578063dd2555dd1461023b578063f2fde38b1461024e575f80fd5b80638da5cb5b146101a8578063944b4468146101c2578063b12ce0b4146101cb578063ba3b7bad146101ea575f80fd5b806369f583f2116100d957806369f583f2146101715780636c7da48f14610184578063715018a6146101975780637c90d3c71461019f575f80fd5b8063016d47b51461010a57806325b2a93b1461011f5780632ae0d1411461013b578063326611f81461014e575b5f80fd5b61011d610118366004612c5d565b610261565b005b61012860035481565b6040519081526020015b60405180910390f35b61011d610149366004612cee565b610310565b61016161015c366004612d1f565b610342565b6040519015158152602001610132565b61016161017f366004612d1f565b610359565b610128610192366004612d36565b61036b565b61011d610414565b61012861271081565b5f546040516001600160a01b039091168152602001610132565b61012860025481565b6101286101d9366004612d1f565b60046020525f908152604090205481565b6101616101f8366004612d1f565b610427565b61012861020b366004612d7f565b610439565b61016161021e366004612dd0565b60056020525f908152604090205460ff1681565b61012860015481565b610128610249366004612de9565b6104e9565b61011d61025c366004612dd0565b61056f565b335f9081526005602052604090205460ff166102905760405163f25c884f60e01b815260040160405180910390fd5b8281146102b05760405163512509d360e11b815260040160405180910390fd5b5f5b83811015610309578282828181106102cc576102cc612e12565b9050602002013560045f8787858181106102e8576102e8612e12565b602090810292909201358352508101919091526040015f20556001016102b2565b5050505050565b6103186105b1565b6001600160a01b03919091165f908152600560205260409020805460ff1916911515919091179055565b5f61034b6105b1565b50600381905560015b919050565b5f6103626105b1565b50600255600190565b5f80610379856103606105dd565b5f86815260046020526040812054919250819003610395575f80fd5b6103a08585836104e9565b90505f6103cf662386f26fc100006103c98a6103bc575f6103bf565b60015b888a885f896105f1565b906105dd565b90505f6103f06402540be4006103c96003548961073390919063ffffffff16565b90508181111561040557935061040b92505050565b50925050505b95945050505050565b61041c6105b1565b6104255f610766565b565b5f6104306105b1565b50600190815590565b5f8061044b6103606103c988426107b5565b5f8681526004602052604081205491925081900361047c57604051630b3951db60e11b815260040160405180910390fd5b6104878585836104e9565b90505f6104a3662386f26fc100006103c98b6103bc575f6103bf565b90505f6104c46402540be4006103c96003548961073390919063ffffffff16565b9050818111156104d95793506104df92505050565b50925050505b9695505050505050565b5f80610506846103c9612710610500896064610733565b90610733565b9050838511156105245761051d81620f42406107b5565b9050610534565b610531620f4240826107b5565b90505b5f6105506127106103c96002548561073390919063ffffffff16565b60015461055d9190612e3a565b90506104df6127106103c98684610733565b6105776105b1565b6001600160a01b0381166105a557604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6105ae81610766565b50565b5f546001600160a01b031633146104255760405163118cdaa760e01b815233600482015260240161059c565b5f6105e88284612e61565b90505b92915050565b5f806105fc876107d0565b90505f610608876107d0565b90505f610627610617886107d0565b610622618e946107d0565b610833565b90505f610641610636886107d0565b6106226127106107d0565b90505f61065a610650886107d0565b61062260646107d0565b90505f6106ab61069e6106756106708989610833565b610aed565b610693610698876106938861068e8a61062260026107d0565b610b0f565b610d6c565b88610b0f565b6106228461068e88611121565b90505f6106c4826106bf8561068e89611121565b6112f3565b905060ff8e16610705576106f76106f26106e289858a898b88611304565b61068e662386f26fc100006107d0565b611348565b9750505050505050506104df565b5f1960ff8f1601610724576106f76106f26106e2888789868d896113c8565b5f9750505050505050506104df565b5f825f0361074257505f6105eb565b61074c8284612e80565b9050816107598483612e61565b146105eb576105eb612e97565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f828211156107c6576107c6612e97565b6105e88284612eab565b5f815f036107df57505f919050565b815f6107ea82611424565b90506070811015610803578060700382901b9150610816565b6070811115610816576070810382901c91505b613fff0160701b6001600160701b03919091161760801b92915050565b5f617fff60f084811c8216919084901c8116908290036108775780617fff03610866575061ffff60ef1b91506105eb9050565b505050600160ff1b811682186105eb565b80617fff036108ba576dffffffffffffffffffffffffffff60801b8416156108a9575061ffff60ef1b91506105eb9050565b505050808218600160ff1b166105eb565b600160801b600160ff1b0384165f0361090857600160801b600160ff1b0385165f036108f0575061ffff60ef1b91506105eb9050565b505050808218600160ff1b16617fff60f01b176105eb565b6001600160701b03608085901c165f829003610927576001915061092e565b600160701b175b6001600160701b03608087901c165f84900361096f57801561096a575f61095482611424565b6001955060e20393840160711901939190911b90505b610979565b600160701b1760721b5b81818161098857610988612e4d565b049050805f036109b657600160ff1b878718166109a5575f6109ab565b600160ff1b5b9450505050506105eb565b6001606c1b8110156109ca576109ca612e97565b5f600160731b821015610a0857600160721b8210156109fd57600160711b8210156109f6576070610a00565b6071610a00565b60725b60ff16610a11565b610a1182611424565b905083614071018186011115610a2e57617fff94505f9150610abe565b83818601613ffc011015610a47575f94505f9150610abe565b83818601613f8c011015610a93578385613ffc011115610a72578385613ffc010382901b9150610a8b565b8385613ffc011015610a8b57613ffc8585030382901c91505b5f9450610abe565b6070811115610aa6576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506105eb565b5f6105eb610afa836114bf565b6f3ffe62e42fefa39ef35793c7673007e560801b5b5f617fff60f084811c8216919084901c811690829003610bac5780617fff03610b89576001600160801b031980851690861603610b5757505050600160ff1b811682186105eb565b6001600160801b031985851816600160ff1b03610b79575050508181176105eb565b5061ffff60ef1b91506105eb9050565b600160801b600160ff1b0384165f03610866575061ffff60ef1b91506105eb9050565b80617fff03610be957600160801b600160ff1b0385165f03610bd8575061ffff60ef1b91506105eb9050565b505050600160ff1b821681186105eb565b6001600160701b03608086901c165f839003610c085760019250610c0f565b600160701b175b6001600160701b03608086901c165f839003610c2e5760019250610c35565b600160701b175b8082029150815f03610c5457600160ff1b878718166109a5575f6109ab565b928201925f600160e11b831015610c8657600160e01b831015610c7f57610c7a83611424565b610c89565b60e0610c89565b60e15b90506140708186011015610ca2575f94505f9250610d3d565b6140e08186011015610ce457614070851015610cc757846140700383901c9250610cdc565b614070851115610cdc57614070850383901b92505b5f9450610d3d565b61c0dd8186011115610cfd57617fff94505f9250610d3d565b6070811115610d14576070810383901c9250610d27565b6070811015610d27578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506105eb565b5f617fff60f084811c8216919084901c811690829003610db75780617fff03610dad576001600160801b031980851690861603610b795784925050506105eb565b84925050506105eb565b80617fff03610dca5783925050506105eb565b6001607f1b608086901c90811015906001600160701b03165f849003610df35760019350610dfa565b600160701b175b6001607f1b608087901c90811015906001600160701b03165f859003610e235760019450610e2a565b600160701b175b825f03610e5b576001600160801b03198816600160ff1b14610e4c5787610e4e565b5f5b96505050505050506105eb565b805f03610e7d576001600160801b03198916600160ff1b14610e4c5788610e4e565b84860382151585151503610f81576070811315610ea357899750505050505050506105eb565b5f811315610eb45790811c90610ee1565b606f19811215610ecd57889750505050505050506105eb565b5f811215610ee157805f0384901c93508596505b92810192600160711b8410610efc576001968701969390931c925b86617fff03610f2d5784610f1557617fff60f01b610f1f565b6001600160f01b03195b9750505050505050506105eb565b600160701b841015610f41575f9650610f4e565b6001600160701b03841693505b83607088901b86610f5f575f610f65565b6001607f1b5b6001600160801b0316171760801b9750505050505050506105eb565b5f811315610f9b57600184901b9350600187039650610fb1565b5f811215610fb157600182901b91506001860396505b6070811315610fc3576001915061100e565b6001811315610fe0576001810360018303901c600101915061100e565b606f19811215610ff3576001935061100e565b5f1981121561100e576001815f030360018503901c60010193505b81841061101f578184039350611028565b83820393508294505b835f0361103f57505f96506105eb95505050505050565b5f61104985611424565b90508060710361106e57600185901c6001600160701b031694506001880197506110bb565b60708110156110ae5760708190038089111561109d578086901b6001600160701b0316955080890398506110a8565b5f985f19019590951b945b506110bb565b6001600160701b03851694505b87617fff036110ed57856110d457617fff60f01b6110de565b6001600160f01b03195b985050505050505050506105eb565b84607089901b876110fe575f611104565b6001607f1b5b6001600160801b0316171760801b985050505050505050506105eb565b5f6001607f1b608083901c111561113e575061ffff60ef1b919050565b617fff60f083901c811690819003611157575090919050565b6001600160701b03608084901c165f829003611176576001915061117d565b600160701b175b805f0361118d57505f9392505050565b613fff8201600190811c92161580156111de57600160701b82106111b757607182901b9150611218565b5f6111c183611424565b60e20360fe16606f19810160011c909403939290921b9150611218565b600160701b82106111f557607082901b9150611218565b5f6111ff83611424565b60e10360fe16606f19810160011c909403939290921b91505b600160701b80830401600190811c9081848161123657611236612e4d565b048201901c9050600181848161124e5761124e612e4d565b048201901c9050600181848161126657611266612e4d565b048201901c9050600181848161127e5761127e612e4d565b048201901c9050600181848161129657611296612e4d565b048201901c905060018184816112ae576112ae612e4d565b048201901c90505f8184816112c5576112c5612e4d565b049050818110156112d4578091505b816001600160701b0316607086901b1760801b95505050505050919050565b5f6105e883600160ff1b8418610d6c565b5f61133d6113158861068e8961166b565b6106bf6113348861068e61132f600160ff1b8b188a610b0f565b611703565b61068e8661166b565b979650505050505050565b5f617fff60f083901c16613fff81101561136457505f92915050565b6001607f1b608084901c10611377575f80fd5b6140fe811115611385575f80fd5b600160701b6001600160701b03608085901c161761406f8210156113af5761406f8290031c6113c1565b61406f8211156113c15761406e1982011b5b9392505050565b5f806113f36113e48961068e61132f600160ff1b8c188b610b0f565b61068e600160ff1b881861166b565b90505f6114098561068e600160ff1b871861166b565b90505f61141683836112f3565b9a9950505050505050505050565b5f808211611430575f80fd5b5f600160801b831061144457608092831c92015b600160401b831061145757604092831c92015b640100000000831061146b57602092831c92015b62010000831061147d57601092831c92015b610100831061148e57600892831c92015b6010831061149e57600492831c92015b600483106114ae57600292831c92015b600283106105eb5760010192915050565b5f6001607f1b608083901c11156114dc575061ffff60ef1b919050565b6001600160801b03198216613fff60f01b036114f957505f919050565b617fff60f083901c811690819003611512575090919050565b6001600160701b03608084901c165f8290036115315760019150611538565b600160701b175b805f0361155057506001600160f01b03199392505050565b5f61406f81613fff85106115745750600f9290921b915f9150613ffe1984016115b2565b60019250600160701b84106115965784613ffe039050600f84901b93506115b2565b5f6115a085611424565b607f8190039590951b9461406d039150505b836001607f1b036115e75782156115c7576001015b5f6115d182611424565b60700390508082901b9150808303925050611632565b5f836115f3575f6115f6565b60015b60ff1690505b600160701b8210156116305793800260ff81901c607f81019190911c945f19939093019260019290921b90821801906115fc565b505b806001600160701b0316607083901b8461164c575f611652565b6001607f1b5b6001600160801b0316171760801b979650505050505050565b5f8061167683611729565b1215611698576105eb61168960016107d0565b6106bf600160ff1b851861166b565b5f6116d96116a660016107d0565b6106226116b360016107d0565b6106936106986116c966083ac553a55e006107d0565b610622662386f26fc100006107d0565b90505f6116e682856117ca565b90506116fb6116f560016107d0565b826112f3565b949350505050565b5f6105eb611724836f1fffb8aa3b295c17f0bbbe87fed0691d60811b610b0f565b6117e0565b5f617fff60f083901c166140fe811115611741575f80fd5b613fff81101561175357505f92915050565b600160701b6001600160701b03608085901c161761406f82101561177d5761406f8290031c61178f565b61406f82111561178f5761406e1982011b5b6001607f1b608085901c106117b757600160ff1b8111156117ae575f80fd5b5f039392505050565b6001600160ff1b038111156113c1575f80fd5b5f6105e86117d783612b30565b61068e85612b77565b5f6001607f1b608083901c90811190617fff60f085901c8116916001600160701b0316908214801561181157508015155b15611825575061ffff60ef1b949350505050565b61400d821115611849578261183f57617fff60f01b61040b565b5f95945050505050565b613f7f8210156118625750613fff60f01b949350505050565b815f036118725760019150611879565b600160701b175b613fef82111561188f57613fee1982011b6118a1565b613fef8210156118a157613fef8290031c5b8280156118b2575061203760811b81115b156118c157505f949350505050565b821580156118e05750713fffffffffffffffffffffffffffffffffff81115b156118f45750617fff60f01b949350505050565b6001600160801b0381169060801c83801561190e57508115155b1561191a579019906001015b6001607f1b8281161561193e5770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6001607e1b831615611961577001306fe0a31b7152de8d5a46305c85edec0260801c5b6001607d1b831615611984577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6001607c1b8316156119a75770010b5586cf9890f6298b92b71842a983630260801c5b6001607b1b8316156119ca577001059b0d31585743ae7c548eb68ca417fd0260801c5b6001607a1b8316156119ed57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b600160791b831615611a105770010163da9fb33356d84a66ae336dcdfa3f0260801c5b600160781b831615611a3357700100b1afa5abcbed6129ab13ec11dc95430260801c5b600160771b831615611a565770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600160761b831615611a79577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600160751b831615611a9c57700100162f3904051fa128bca9c55c31e5df0260801c5b600160741b831615611abf577001000b175effdc76ba38e31671ca9397250260801c5b600160731b831615611ae257700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600160721b831615611b055770010002c5cc37da9491d0985c348c68e7b30260801c5b600160711b831615611b28577001000162e525ee054754457d59952920260260801c5b600160701b831615611b4b5770010000b17255775c040618bf4a4ade83fc0260801c5b6001606f1b831615611b6e577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6001606e1b831615611b9157700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6001606d1b831615611bb45770010000162e43f4f831060e02d839a9d16d0260801c5b6001606c1b831615611bd757700100000b1721bcfc99d9f890ea069117630260801c5b6001606b1b831615611bfa5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6001606a1b831615611c1d577001000002c5c863b73f016468f6bac5ca2b0260801c5b600160691b831615611c4057700100000162e430e5a18f6119e3c02282a50260801c5b600160681b831615611c63577001000000b1721835514b86e6d96efd1bfe0260801c5b600160671b831615611c8657700100000058b90c0b48c6be5df846c5b2ef0260801c5b600160661b831615611ca95770010000002c5c8601cc6b9e94213c72737a0260801c5b600160651b831615611ccc577001000000162e42fff037df38aa2b219f060260801c5b600160641b831615611cef5770010000000b17217fba9c739aa5819f44f90260801c5b600160631b831615611d12577001000000058b90bfcdee5acd3c1cedc8230260801c5b600160621b831615611d3557700100000002c5c85fe31f35a6a30da1be500260801c5b600160611b831615611d585770010000000162e42ff0999ce3541b9fffcf0260801c5b600160601b831615611d7b57700100000000b17217f80f4ef5aadda455540260801c5b6001605f1b831615611d9e5770010000000058b90bfbf8479bd5a81b51ad0260801c5b6001605e1b831615611dc1577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6001605d1b831615611de457700100000000162e42fefb2fed257559bdaa0260801c5b6001605c1b831615611e07577001000000000b17217f7d5a7716bba4a9ae0260801c5b6001605b1b831615611e2a57700100000000058b90bfbe9ddbac5e109cce0260801c5b6001605a1b831615611e4d5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600160591b831615611e70577001000000000162e42fefa494f1478fde050260801c5b600160581b831615611e935770010000000000b17217f7d20cf927c8e94c0260801c5b600160571b831615611eb6577001000000000058b90bfbe8f71cb4e4b33d0260801c5b600160561b831615611ed957700100000000002c5c85fdf477b662b269450260801c5b600160551b831615611efc5770010000000000162e42fefa3ae53369388c0260801c5b600160541b831615611f1f57700100000000000b17217f7d1d351a389d400260801c5b600160531b831615611f425770010000000000058b90bfbe8e8b2d3d4ede0260801c5b600160521b831615611f65577001000000000002c5c85fdf4741bea6e77e0260801c5b600160511b831615611f8857700100000000000162e42fefa39fe95583c20260801c5b600160501b831615611fab577001000000000000b17217f7d1cfb72b45e10260801c5b6980000000000000000000831615611fd457700100000000000058b90bfbe8e7cc35c3f00260801c5b6940000000000000000000831615611ffd5770010000000000002c5c85fdf473e242ea380260801c5b6920000000000000000000831615612026577001000000000000162e42fefa39f02b772c0260801c5b691000000000000000000083161561204f5770010000000000000b17217f7d1cf7d83c1a0260801c5b6908000000000000000000831615612078577001000000000000058b90bfbe8e7bdcbe2e0260801c5b69040000000000000000008316156120a157700100000000000002c5c85fdf473dea871f0260801c5b69020000000000000000008316156120ca5770010000000000000162e42fefa39ef44d910260801c5b69010000000000000000008316156120f357700100000000000000b17217f7d1cf79e9490260801c5b6880000000000000000083161561211b5770010000000000000058b90bfbe8e7bce5440260801c5b68400000000000000000831615612143577001000000000000002c5c85fdf473de6eca0260801c5b6820000000000000000083161561216b57700100000000000000162e42fefa39ef366f0260801c5b68100000000000000000831615612193577001000000000000000b17217f7d1cf79afa0260801c5b680800000000000000008316156121bb57700100000000000000058b90bfbe8e7bcd6d0260801c5b680400000000000000008316156121e35770010000000000000002c5c85fdf473de6b20260801c5b6802000000000000000083161561220b577001000000000000000162e42fefa39ef3580260801c5b600160401b83161561222e5770010000000000000000b17217f7d1cf79ab0260801c5b678000000000000000831615612255577001000000000000000058b90bfbe8e7bcd50260801c5b67400000000000000083161561227c57700100000000000000002c5c85fdf473de6a0260801c5b6720000000000000008316156122a35770010000000000000000162e42fefa39ef340260801c5b6710000000000000008316156122ca57700100000000000000000b17217f7d1cf7990260801c5b6708000000000000008316156122f15770010000000000000000058b90bfbe8e7bcc0260801c5b670400000000000000831615612318577001000000000000000002c5c85fdf473de50260801c5b67020000000000000083161561233f57700100000000000000000162e42fefa39ef20260801c5b670100000000000000831615612366577001000000000000000000b17217f7d1cf780260801c5b668000000000000083161561238c57700100000000000000000058b90bfbe8e7bb0260801c5b66400000000000008316156123b25770010000000000000000002c5c85fdf473dd0260801c5b66200000000000008316156123d8577001000000000000000000162e42fefa39ee0260801c5b66100000000000008316156123fe5770010000000000000000000b17217f7d1cf60260801c5b6608000000000000831615612424577001000000000000000000058b90bfbe8e7a0260801c5b660400000000000083161561244a57700100000000000000000002c5c85fdf473c0260801c5b66020000000000008316156124705770010000000000000000000162e42fefa39d0260801c5b660100000000000083161561249657700100000000000000000000b17217f7d1ce0260801c5b658000000000008316156124bb5770010000000000000000000058b90bfbe8e60260801c5b654000000000008316156124e0577001000000000000000000002c5c85fdf4720260801c5b6520000000000083161561250557700100000000000000000000162e42fefa380260801c5b6510000000000083161561252a577001000000000000000000000b17217f7d1b0260801c5b6508000000000083161561254f57700100000000000000000000058b90bfbe8d0260801c5b650400000000008316156125745770010000000000000000000002c5c85fdf460260801c5b65020000000000831615612599577001000000000000000000000162e42fefa20260801c5b650100000000008316156125be5770010000000000000000000000b17217f7d00260801c5b6480000000008316156125e2577001000000000000000000000058b90bfbe70260801c5b64400000000083161561260657700100000000000000000000002c5c85fdf30260801c5b64200000000083161561262a5770010000000000000000000000162e42fef90260801c5b64100000000083161561264e57700100000000000000000000000b17217f7c0260801c5b6408000000008316156126725770010000000000000000000000058b90bfbd0260801c5b640400000000831615612696577001000000000000000000000002c5c85fde0260801c5b6402000000008316156126ba57700100000000000000000000000162e42fee0260801c5b6401000000008316156126de577001000000000000000000000000b17217f60260801c5b638000000083161561270157700100000000000000000000000058b90bfa0260801c5b63400000008316156127245770010000000000000000000000002c5c85fc0260801c5b6320000000831615612747577001000000000000000000000000162e42fd0260801c5b631000000083161561276a5770010000000000000000000000000b17217e0260801c5b630800000083161561278d577001000000000000000000000000058b90be0260801c5b63040000008316156127b057700100000000000000000000000002c5c85e0260801c5b63020000008316156127d35770010000000000000000000000000162e42e0260801c5b63010000008316156127f657700100000000000000000000000000b172160260801c5b628000008316156128185770010000000000000000000000000058b90a0260801c5b6240000083161561283a577001000000000000000000000000002c5c840260801c5b6220000083161561285c57700100000000000000000000000000162e410260801c5b6210000083161561287e577001000000000000000000000000000b17200260801c5b620800008316156128a057700100000000000000000000000000058b8f0260801c5b620400008316156128c25770010000000000000000000000000002c5c70260801c5b620200008316156128e4577001000000000000000000000000000162e30260801c5b620100008316156129065770010000000000000000000000000000b1710260801c5b618000831615612927577001000000000000000000000000000058b80260801c5b61400083161561294857700100000000000000000000000000002c5b0260801c5b6120008316156129695770010000000000000000000000000000162d0260801c5b61100083161561298a57700100000000000000000000000000000b160260801c5b6108008316156129ab5770010000000000000000000000000000058a0260801c5b6104008316156129cc577001000000000000000000000000000002c40260801c5b6102008316156129ed577001000000000000000000000000000001610260801c5b610100831615612a0e577001000000000000000000000000000000b00260801c5b6080831615612a2e577001000000000000000000000000000000570260801c5b6040831615612a4e5770010000000000000000000000000000002b0260801c5b6020831615612a6e577001000000000000000000000000000000150260801c5b6010831615612a8e5770010000000000000000000000000000000a0260801c5b6008831615612aae577001000000000000000000000000000000040260801c5b6004831615612ace577001000000000000000000000000000000010260801c5b84612aef57600f81901c6001600160701b03169050613fff82019150612b1d565b613ffe8211612b1457600f81901c6001600160701b0316905081613fff039150612b1d565b5f91613fee19011c5b60709190911b1760801b95945050505050565b5f6105eb612b4f61132f600160ff1b851861068e8661062260026107d0565b610622612b72612b5f60026107d0565b61068e6116c9666f9c9e651c44806107d0565b611121565b5f6105eb612bda612b916116c9660b58c2126f49006107d0565b6106938561068e612bb7612bae6116c9660caaedbfa8a7006107d0565b600160ff1b1890565b6106938961068e612bd16116c9663f4a728c19ce806107d0565b6106938d612be0565b83610b0f565b5f6105eb8261068e612bfe612bae6116c96640b43a042331006107d0565b6106938661068e6116c9662f42c683f17c806107d0565b5f8083601f840112612c25575f80fd5b50813567ffffffffffffffff811115612c3c575f80fd5b6020830191508360208260051b8501011115612c56575f80fd5b9250929050565b5f805f8060408587031215612c70575f80fd5b843567ffffffffffffffff811115612c86575f80fd5b612c9287828801612c15565b909550935050602085013567ffffffffffffffff811115612cb1575f80fd5b612cbd87828801612c15565b95989497509550505050565b80356001600160a01b0381168114610354575f80fd5b80358015158114610354575f80fd5b5f8060408385031215612cff575f80fd5b612d0883612cc9565b9150612d1660208401612cdf565b90509250929050565b5f60208284031215612d2f575f80fd5b5035919050565b5f805f805f60a08688031215612d4a575f80fd5b612d5386612cc9565b9450612d6160208701612cdf565b94979496505050506040830135926060810135926080909101359150565b5f805f805f8060c08789031215612d94575f80fd5b612d9d87612cc9565b9550612dab60208801612cdf565b95989597505050506040840135936060810135936080820135935060a0909101359150565b5f60208284031215612de0575f80fd5b6105e882612cc9565b5f805f60608486031215612dfb575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156105eb576105eb612e26565b634e487b7160e01b5f52601260045260245ffd5b5f82612e7b57634e487b7160e01b5f52601260045260245ffd5b500490565b80820281158282048414176105eb576105eb612e26565b634e487b7160e01b5f52600160045260245ffd5b818103818111156105eb576105eb612e2656fea26469706673582212208088e9cadd30addb31b21eed9e976fa478fdb5ac34143e11380fb85ae4df17f064736f6c634300081a0033000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000989680
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610106575f3560e01c80638da5cb5b1161009e578063c83ffad21161006e578063c83ffad2146101fd578063d5f1b2ce14610210578063d82940a314610232578063dd2555dd1461023b578063f2fde38b1461024e575f80fd5b80638da5cb5b146101a8578063944b4468146101c2578063b12ce0b4146101cb578063ba3b7bad146101ea575f80fd5b806369f583f2116100d957806369f583f2146101715780636c7da48f14610184578063715018a6146101975780637c90d3c71461019f575f80fd5b8063016d47b51461010a57806325b2a93b1461011f5780632ae0d1411461013b578063326611f81461014e575b5f80fd5b61011d610118366004612c5d565b610261565b005b61012860035481565b6040519081526020015b60405180910390f35b61011d610149366004612cee565b610310565b61016161015c366004612d1f565b610342565b6040519015158152602001610132565b61016161017f366004612d1f565b610359565b610128610192366004612d36565b61036b565b61011d610414565b61012861271081565b5f546040516001600160a01b039091168152602001610132565b61012860025481565b6101286101d9366004612d1f565b60046020525f908152604090205481565b6101616101f8366004612d1f565b610427565b61012861020b366004612d7f565b610439565b61016161021e366004612dd0565b60056020525f908152604090205460ff1681565b61012860015481565b610128610249366004612de9565b6104e9565b61011d61025c366004612dd0565b61056f565b335f9081526005602052604090205460ff166102905760405163f25c884f60e01b815260040160405180910390fd5b8281146102b05760405163512509d360e11b815260040160405180910390fd5b5f5b83811015610309578282828181106102cc576102cc612e12565b9050602002013560045f8787858181106102e8576102e8612e12565b602090810292909201358352508101919091526040015f20556001016102b2565b5050505050565b6103186105b1565b6001600160a01b03919091165f908152600560205260409020805460ff1916911515919091179055565b5f61034b6105b1565b50600381905560015b919050565b5f6103626105b1565b50600255600190565b5f80610379856103606105dd565b5f86815260046020526040812054919250819003610395575f80fd5b6103a08585836104e9565b90505f6103cf662386f26fc100006103c98a6103bc575f6103bf565b60015b888a885f896105f1565b906105dd565b90505f6103f06402540be4006103c96003548961073390919063ffffffff16565b90508181111561040557935061040b92505050565b50925050505b95945050505050565b61041c6105b1565b6104255f610766565b565b5f6104306105b1565b50600190815590565b5f8061044b6103606103c988426107b5565b5f8681526004602052604081205491925081900361047c57604051630b3951db60e11b815260040160405180910390fd5b6104878585836104e9565b90505f6104a3662386f26fc100006103c98b6103bc575f6103bf565b90505f6104c46402540be4006103c96003548961073390919063ffffffff16565b9050818111156104d95793506104df92505050565b50925050505b9695505050505050565b5f80610506846103c9612710610500896064610733565b90610733565b9050838511156105245761051d81620f42406107b5565b9050610534565b610531620f4240826107b5565b90505b5f6105506127106103c96002548561073390919063ffffffff16565b60015461055d9190612e3a565b90506104df6127106103c98684610733565b6105776105b1565b6001600160a01b0381166105a557604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6105ae81610766565b50565b5f546001600160a01b031633146104255760405163118cdaa760e01b815233600482015260240161059c565b5f6105e88284612e61565b90505b92915050565b5f806105fc876107d0565b90505f610608876107d0565b90505f610627610617886107d0565b610622618e946107d0565b610833565b90505f610641610636886107d0565b6106226127106107d0565b90505f61065a610650886107d0565b61062260646107d0565b90505f6106ab61069e6106756106708989610833565b610aed565b610693610698876106938861068e8a61062260026107d0565b610b0f565b610d6c565b88610b0f565b6106228461068e88611121565b90505f6106c4826106bf8561068e89611121565b6112f3565b905060ff8e16610705576106f76106f26106e289858a898b88611304565b61068e662386f26fc100006107d0565b611348565b9750505050505050506104df565b5f1960ff8f1601610724576106f76106f26106e2888789868d896113c8565b5f9750505050505050506104df565b5f825f0361074257505f6105eb565b61074c8284612e80565b9050816107598483612e61565b146105eb576105eb612e97565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f828211156107c6576107c6612e97565b6105e88284612eab565b5f815f036107df57505f919050565b815f6107ea82611424565b90506070811015610803578060700382901b9150610816565b6070811115610816576070810382901c91505b613fff0160701b6001600160701b03919091161760801b92915050565b5f617fff60f084811c8216919084901c8116908290036108775780617fff03610866575061ffff60ef1b91506105eb9050565b505050600160ff1b811682186105eb565b80617fff036108ba576dffffffffffffffffffffffffffff60801b8416156108a9575061ffff60ef1b91506105eb9050565b505050808218600160ff1b166105eb565b600160801b600160ff1b0384165f0361090857600160801b600160ff1b0385165f036108f0575061ffff60ef1b91506105eb9050565b505050808218600160ff1b16617fff60f01b176105eb565b6001600160701b03608085901c165f829003610927576001915061092e565b600160701b175b6001600160701b03608087901c165f84900361096f57801561096a575f61095482611424565b6001955060e20393840160711901939190911b90505b610979565b600160701b1760721b5b81818161098857610988612e4d565b049050805f036109b657600160ff1b878718166109a5575f6109ab565b600160ff1b5b9450505050506105eb565b6001606c1b8110156109ca576109ca612e97565b5f600160731b821015610a0857600160721b8210156109fd57600160711b8210156109f6576070610a00565b6071610a00565b60725b60ff16610a11565b610a1182611424565b905083614071018186011115610a2e57617fff94505f9150610abe565b83818601613ffc011015610a47575f94505f9150610abe565b83818601613f8c011015610a93578385613ffc011115610a72578385613ffc010382901b9150610a8b565b8385613ffc011015610a8b57613ffc8585030382901c91505b5f9450610abe565b6070811115610aa6576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506105eb565b5f6105eb610afa836114bf565b6f3ffe62e42fefa39ef35793c7673007e560801b5b5f617fff60f084811c8216919084901c811690829003610bac5780617fff03610b89576001600160801b031980851690861603610b5757505050600160ff1b811682186105eb565b6001600160801b031985851816600160ff1b03610b79575050508181176105eb565b5061ffff60ef1b91506105eb9050565b600160801b600160ff1b0384165f03610866575061ffff60ef1b91506105eb9050565b80617fff03610be957600160801b600160ff1b0385165f03610bd8575061ffff60ef1b91506105eb9050565b505050600160ff1b821681186105eb565b6001600160701b03608086901c165f839003610c085760019250610c0f565b600160701b175b6001600160701b03608086901c165f839003610c2e5760019250610c35565b600160701b175b8082029150815f03610c5457600160ff1b878718166109a5575f6109ab565b928201925f600160e11b831015610c8657600160e01b831015610c7f57610c7a83611424565b610c89565b60e0610c89565b60e15b90506140708186011015610ca2575f94505f9250610d3d565b6140e08186011015610ce457614070851015610cc757846140700383901c9250610cdc565b614070851115610cdc57614070850383901b92505b5f9450610d3d565b61c0dd8186011115610cfd57617fff94505f9250610d3d565b6070811115610d14576070810383901c9250610d27565b6070811015610d27578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506105eb565b5f617fff60f084811c8216919084901c811690829003610db75780617fff03610dad576001600160801b031980851690861603610b795784925050506105eb565b84925050506105eb565b80617fff03610dca5783925050506105eb565b6001607f1b608086901c90811015906001600160701b03165f849003610df35760019350610dfa565b600160701b175b6001607f1b608087901c90811015906001600160701b03165f859003610e235760019450610e2a565b600160701b175b825f03610e5b576001600160801b03198816600160ff1b14610e4c5787610e4e565b5f5b96505050505050506105eb565b805f03610e7d576001600160801b03198916600160ff1b14610e4c5788610e4e565b84860382151585151503610f81576070811315610ea357899750505050505050506105eb565b5f811315610eb45790811c90610ee1565b606f19811215610ecd57889750505050505050506105eb565b5f811215610ee157805f0384901c93508596505b92810192600160711b8410610efc576001968701969390931c925b86617fff03610f2d5784610f1557617fff60f01b610f1f565b6001600160f01b03195b9750505050505050506105eb565b600160701b841015610f41575f9650610f4e565b6001600160701b03841693505b83607088901b86610f5f575f610f65565b6001607f1b5b6001600160801b0316171760801b9750505050505050506105eb565b5f811315610f9b57600184901b9350600187039650610fb1565b5f811215610fb157600182901b91506001860396505b6070811315610fc3576001915061100e565b6001811315610fe0576001810360018303901c600101915061100e565b606f19811215610ff3576001935061100e565b5f1981121561100e576001815f030360018503901c60010193505b81841061101f578184039350611028565b83820393508294505b835f0361103f57505f96506105eb95505050505050565b5f61104985611424565b90508060710361106e57600185901c6001600160701b031694506001880197506110bb565b60708110156110ae5760708190038089111561109d578086901b6001600160701b0316955080890398506110a8565b5f985f19019590951b945b506110bb565b6001600160701b03851694505b87617fff036110ed57856110d457617fff60f01b6110de565b6001600160f01b03195b985050505050505050506105eb565b84607089901b876110fe575f611104565b6001607f1b5b6001600160801b0316171760801b985050505050505050506105eb565b5f6001607f1b608083901c111561113e575061ffff60ef1b919050565b617fff60f083901c811690819003611157575090919050565b6001600160701b03608084901c165f829003611176576001915061117d565b600160701b175b805f0361118d57505f9392505050565b613fff8201600190811c92161580156111de57600160701b82106111b757607182901b9150611218565b5f6111c183611424565b60e20360fe16606f19810160011c909403939290921b9150611218565b600160701b82106111f557607082901b9150611218565b5f6111ff83611424565b60e10360fe16606f19810160011c909403939290921b91505b600160701b80830401600190811c9081848161123657611236612e4d565b048201901c9050600181848161124e5761124e612e4d565b048201901c9050600181848161126657611266612e4d565b048201901c9050600181848161127e5761127e612e4d565b048201901c9050600181848161129657611296612e4d565b048201901c905060018184816112ae576112ae612e4d565b048201901c90505f8184816112c5576112c5612e4d565b049050818110156112d4578091505b816001600160701b0316607086901b1760801b95505050505050919050565b5f6105e883600160ff1b8418610d6c565b5f61133d6113158861068e8961166b565b6106bf6113348861068e61132f600160ff1b8b188a610b0f565b611703565b61068e8661166b565b979650505050505050565b5f617fff60f083901c16613fff81101561136457505f92915050565b6001607f1b608084901c10611377575f80fd5b6140fe811115611385575f80fd5b600160701b6001600160701b03608085901c161761406f8210156113af5761406f8290031c6113c1565b61406f8211156113c15761406e1982011b5b9392505050565b5f806113f36113e48961068e61132f600160ff1b8c188b610b0f565b61068e600160ff1b881861166b565b90505f6114098561068e600160ff1b871861166b565b90505f61141683836112f3565b9a9950505050505050505050565b5f808211611430575f80fd5b5f600160801b831061144457608092831c92015b600160401b831061145757604092831c92015b640100000000831061146b57602092831c92015b62010000831061147d57601092831c92015b610100831061148e57600892831c92015b6010831061149e57600492831c92015b600483106114ae57600292831c92015b600283106105eb5760010192915050565b5f6001607f1b608083901c11156114dc575061ffff60ef1b919050565b6001600160801b03198216613fff60f01b036114f957505f919050565b617fff60f083901c811690819003611512575090919050565b6001600160701b03608084901c165f8290036115315760019150611538565b600160701b175b805f0361155057506001600160f01b03199392505050565b5f61406f81613fff85106115745750600f9290921b915f9150613ffe1984016115b2565b60019250600160701b84106115965784613ffe039050600f84901b93506115b2565b5f6115a085611424565b607f8190039590951b9461406d039150505b836001607f1b036115e75782156115c7576001015b5f6115d182611424565b60700390508082901b9150808303925050611632565b5f836115f3575f6115f6565b60015b60ff1690505b600160701b8210156116305793800260ff81901c607f81019190911c945f19939093019260019290921b90821801906115fc565b505b806001600160701b0316607083901b8461164c575f611652565b6001607f1b5b6001600160801b0316171760801b979650505050505050565b5f8061167683611729565b1215611698576105eb61168960016107d0565b6106bf600160ff1b851861166b565b5f6116d96116a660016107d0565b6106226116b360016107d0565b6106936106986116c966083ac553a55e006107d0565b610622662386f26fc100006107d0565b90505f6116e682856117ca565b90506116fb6116f560016107d0565b826112f3565b949350505050565b5f6105eb611724836f1fffb8aa3b295c17f0bbbe87fed0691d60811b610b0f565b6117e0565b5f617fff60f083901c166140fe811115611741575f80fd5b613fff81101561175357505f92915050565b600160701b6001600160701b03608085901c161761406f82101561177d5761406f8290031c61178f565b61406f82111561178f5761406e1982011b5b6001607f1b608085901c106117b757600160ff1b8111156117ae575f80fd5b5f039392505050565b6001600160ff1b038111156113c1575f80fd5b5f6105e86117d783612b30565b61068e85612b77565b5f6001607f1b608083901c90811190617fff60f085901c8116916001600160701b0316908214801561181157508015155b15611825575061ffff60ef1b949350505050565b61400d821115611849578261183f57617fff60f01b61040b565b5f95945050505050565b613f7f8210156118625750613fff60f01b949350505050565b815f036118725760019150611879565b600160701b175b613fef82111561188f57613fee1982011b6118a1565b613fef8210156118a157613fef8290031c5b8280156118b2575061203760811b81115b156118c157505f949350505050565b821580156118e05750713fffffffffffffffffffffffffffffffffff81115b156118f45750617fff60f01b949350505050565b6001600160801b0381169060801c83801561190e57508115155b1561191a579019906001015b6001607f1b8281161561193e5770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6001607e1b831615611961577001306fe0a31b7152de8d5a46305c85edec0260801c5b6001607d1b831615611984577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6001607c1b8316156119a75770010b5586cf9890f6298b92b71842a983630260801c5b6001607b1b8316156119ca577001059b0d31585743ae7c548eb68ca417fd0260801c5b6001607a1b8316156119ed57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b600160791b831615611a105770010163da9fb33356d84a66ae336dcdfa3f0260801c5b600160781b831615611a3357700100b1afa5abcbed6129ab13ec11dc95430260801c5b600160771b831615611a565770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600160761b831615611a79577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600160751b831615611a9c57700100162f3904051fa128bca9c55c31e5df0260801c5b600160741b831615611abf577001000b175effdc76ba38e31671ca9397250260801c5b600160731b831615611ae257700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600160721b831615611b055770010002c5cc37da9491d0985c348c68e7b30260801c5b600160711b831615611b28577001000162e525ee054754457d59952920260260801c5b600160701b831615611b4b5770010000b17255775c040618bf4a4ade83fc0260801c5b6001606f1b831615611b6e577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6001606e1b831615611b9157700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6001606d1b831615611bb45770010000162e43f4f831060e02d839a9d16d0260801c5b6001606c1b831615611bd757700100000b1721bcfc99d9f890ea069117630260801c5b6001606b1b831615611bfa5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6001606a1b831615611c1d577001000002c5c863b73f016468f6bac5ca2b0260801c5b600160691b831615611c4057700100000162e430e5a18f6119e3c02282a50260801c5b600160681b831615611c63577001000000b1721835514b86e6d96efd1bfe0260801c5b600160671b831615611c8657700100000058b90c0b48c6be5df846c5b2ef0260801c5b600160661b831615611ca95770010000002c5c8601cc6b9e94213c72737a0260801c5b600160651b831615611ccc577001000000162e42fff037df38aa2b219f060260801c5b600160641b831615611cef5770010000000b17217fba9c739aa5819f44f90260801c5b600160631b831615611d12577001000000058b90bfcdee5acd3c1cedc8230260801c5b600160621b831615611d3557700100000002c5c85fe31f35a6a30da1be500260801c5b600160611b831615611d585770010000000162e42ff0999ce3541b9fffcf0260801c5b600160601b831615611d7b57700100000000b17217f80f4ef5aadda455540260801c5b6001605f1b831615611d9e5770010000000058b90bfbf8479bd5a81b51ad0260801c5b6001605e1b831615611dc1577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6001605d1b831615611de457700100000000162e42fefb2fed257559bdaa0260801c5b6001605c1b831615611e07577001000000000b17217f7d5a7716bba4a9ae0260801c5b6001605b1b831615611e2a57700100000000058b90bfbe9ddbac5e109cce0260801c5b6001605a1b831615611e4d5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600160591b831615611e70577001000000000162e42fefa494f1478fde050260801c5b600160581b831615611e935770010000000000b17217f7d20cf927c8e94c0260801c5b600160571b831615611eb6577001000000000058b90bfbe8f71cb4e4b33d0260801c5b600160561b831615611ed957700100000000002c5c85fdf477b662b269450260801c5b600160551b831615611efc5770010000000000162e42fefa3ae53369388c0260801c5b600160541b831615611f1f57700100000000000b17217f7d1d351a389d400260801c5b600160531b831615611f425770010000000000058b90bfbe8e8b2d3d4ede0260801c5b600160521b831615611f65577001000000000002c5c85fdf4741bea6e77e0260801c5b600160511b831615611f8857700100000000000162e42fefa39fe95583c20260801c5b600160501b831615611fab577001000000000000b17217f7d1cfb72b45e10260801c5b6980000000000000000000831615611fd457700100000000000058b90bfbe8e7cc35c3f00260801c5b6940000000000000000000831615611ffd5770010000000000002c5c85fdf473e242ea380260801c5b6920000000000000000000831615612026577001000000000000162e42fefa39f02b772c0260801c5b691000000000000000000083161561204f5770010000000000000b17217f7d1cf7d83c1a0260801c5b6908000000000000000000831615612078577001000000000000058b90bfbe8e7bdcbe2e0260801c5b69040000000000000000008316156120a157700100000000000002c5c85fdf473dea871f0260801c5b69020000000000000000008316156120ca5770010000000000000162e42fefa39ef44d910260801c5b69010000000000000000008316156120f357700100000000000000b17217f7d1cf79e9490260801c5b6880000000000000000083161561211b5770010000000000000058b90bfbe8e7bce5440260801c5b68400000000000000000831615612143577001000000000000002c5c85fdf473de6eca0260801c5b6820000000000000000083161561216b57700100000000000000162e42fefa39ef366f0260801c5b68100000000000000000831615612193577001000000000000000b17217f7d1cf79afa0260801c5b680800000000000000008316156121bb57700100000000000000058b90bfbe8e7bcd6d0260801c5b680400000000000000008316156121e35770010000000000000002c5c85fdf473de6b20260801c5b6802000000000000000083161561220b577001000000000000000162e42fefa39ef3580260801c5b600160401b83161561222e5770010000000000000000b17217f7d1cf79ab0260801c5b678000000000000000831615612255577001000000000000000058b90bfbe8e7bcd50260801c5b67400000000000000083161561227c57700100000000000000002c5c85fdf473de6a0260801c5b6720000000000000008316156122a35770010000000000000000162e42fefa39ef340260801c5b6710000000000000008316156122ca57700100000000000000000b17217f7d1cf7990260801c5b6708000000000000008316156122f15770010000000000000000058b90bfbe8e7bcc0260801c5b670400000000000000831615612318577001000000000000000002c5c85fdf473de50260801c5b67020000000000000083161561233f57700100000000000000000162e42fefa39ef20260801c5b670100000000000000831615612366577001000000000000000000b17217f7d1cf780260801c5b668000000000000083161561238c57700100000000000000000058b90bfbe8e7bb0260801c5b66400000000000008316156123b25770010000000000000000002c5c85fdf473dd0260801c5b66200000000000008316156123d8577001000000000000000000162e42fefa39ee0260801c5b66100000000000008316156123fe5770010000000000000000000b17217f7d1cf60260801c5b6608000000000000831615612424577001000000000000000000058b90bfbe8e7a0260801c5b660400000000000083161561244a57700100000000000000000002c5c85fdf473c0260801c5b66020000000000008316156124705770010000000000000000000162e42fefa39d0260801c5b660100000000000083161561249657700100000000000000000000b17217f7d1ce0260801c5b658000000000008316156124bb5770010000000000000000000058b90bfbe8e60260801c5b654000000000008316156124e0577001000000000000000000002c5c85fdf4720260801c5b6520000000000083161561250557700100000000000000000000162e42fefa380260801c5b6510000000000083161561252a577001000000000000000000000b17217f7d1b0260801c5b6508000000000083161561254f57700100000000000000000000058b90bfbe8d0260801c5b650400000000008316156125745770010000000000000000000002c5c85fdf460260801c5b65020000000000831615612599577001000000000000000000000162e42fefa20260801c5b650100000000008316156125be5770010000000000000000000000b17217f7d00260801c5b6480000000008316156125e2577001000000000000000000000058b90bfbe70260801c5b64400000000083161561260657700100000000000000000000002c5c85fdf30260801c5b64200000000083161561262a5770010000000000000000000000162e42fef90260801c5b64100000000083161561264e57700100000000000000000000000b17217f7c0260801c5b6408000000008316156126725770010000000000000000000000058b90bfbd0260801c5b640400000000831615612696577001000000000000000000000002c5c85fde0260801c5b6402000000008316156126ba57700100000000000000000000000162e42fee0260801c5b6401000000008316156126de577001000000000000000000000000b17217f60260801c5b638000000083161561270157700100000000000000000000000058b90bfa0260801c5b63400000008316156127245770010000000000000000000000002c5c85fc0260801c5b6320000000831615612747577001000000000000000000000000162e42fd0260801c5b631000000083161561276a5770010000000000000000000000000b17217e0260801c5b630800000083161561278d577001000000000000000000000000058b90be0260801c5b63040000008316156127b057700100000000000000000000000002c5c85e0260801c5b63020000008316156127d35770010000000000000000000000000162e42e0260801c5b63010000008316156127f657700100000000000000000000000000b172160260801c5b628000008316156128185770010000000000000000000000000058b90a0260801c5b6240000083161561283a577001000000000000000000000000002c5c840260801c5b6220000083161561285c57700100000000000000000000000000162e410260801c5b6210000083161561287e577001000000000000000000000000000b17200260801c5b620800008316156128a057700100000000000000000000000000058b8f0260801c5b620400008316156128c25770010000000000000000000000000002c5c70260801c5b620200008316156128e4577001000000000000000000000000000162e30260801c5b620100008316156129065770010000000000000000000000000000b1710260801c5b618000831615612927577001000000000000000000000000000058b80260801c5b61400083161561294857700100000000000000000000000000002c5b0260801c5b6120008316156129695770010000000000000000000000000000162d0260801c5b61100083161561298a57700100000000000000000000000000000b160260801c5b6108008316156129ab5770010000000000000000000000000000058a0260801c5b6104008316156129cc577001000000000000000000000000000002c40260801c5b6102008316156129ed577001000000000000000000000000000001610260801c5b610100831615612a0e577001000000000000000000000000000000b00260801c5b6080831615612a2e577001000000000000000000000000000000570260801c5b6040831615612a4e5770010000000000000000000000000000002b0260801c5b6020831615612a6e577001000000000000000000000000000000150260801c5b6010831615612a8e5770010000000000000000000000000000000a0260801c5b6008831615612aae577001000000000000000000000000000000040260801c5b6004831615612ace577001000000000000000000000000000000010260801c5b84612aef57600f81901c6001600160701b03169050613fff82019150612b1d565b613ffe8211612b1457600f81901c6001600160701b0316905081613fff039150612b1d565b5f91613fee19011c5b60709190911b1760801b95945050505050565b5f6105eb612b4f61132f600160ff1b851861068e8661062260026107d0565b610622612b72612b5f60026107d0565b61068e6116c9666f9c9e651c44806107d0565b611121565b5f6105eb612bda612b916116c9660b58c2126f49006107d0565b6106938561068e612bb7612bae6116c9660caaedbfa8a7006107d0565b600160ff1b1890565b6106938961068e612bd16116c9663f4a728c19ce806107d0565b6106938d612be0565b83610b0f565b5f6105eb8261068e612bfe612bae6116c96640b43a042331006107d0565b6106938661068e6116c9662f42c683f17c806107d0565b5f8083601f840112612c25575f80fd5b50813567ffffffffffffffff811115612c3c575f80fd5b6020830191508360208260051b8501011115612c56575f80fd5b9250929050565b5f805f8060408587031215612c70575f80fd5b843567ffffffffffffffff811115612c86575f80fd5b612c9287828801612c15565b909550935050602085013567ffffffffffffffff811115612cb1575f80fd5b612cbd87828801612c15565b95989497509550505050565b80356001600160a01b0381168114610354575f80fd5b80358015158114610354575f80fd5b5f8060408385031215612cff575f80fd5b612d0883612cc9565b9150612d1660208401612cdf565b90509250929050565b5f60208284031215612d2f575f80fd5b5035919050565b5f805f805f60a08688031215612d4a575f80fd5b612d5386612cc9565b9450612d6160208701612cdf565b94979496505050506040830135926060810135926080909101359150565b5f805f805f8060c08789031215612d94575f80fd5b612d9d87612cc9565b9550612dab60208801612cdf565b95989597505050506040840135936060810135936080820135935060a0909101359150565b5f60208284031215612de0575f80fd5b6105e882612cc9565b5f805f60608486031215612dfb575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156105eb576105eb612e26565b634e487b7160e01b5f52601260045260245ffd5b5f82612e7b57634e487b7160e01b5f52601260045260245ffd5b500490565b80820281158282048414176105eb576105eb612e26565b634e487b7160e01b5f52600160045260245ffd5b818103818111156105eb576105eb612e2656fea26469706673582212208088e9cadd30addb31b21eed9e976fa478fdb5ac34143e11380fb85ae4df17f064736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000989680
-----Decoded View---------------
Arg [0] : _volatilityOffset (uint256): 10000
Arg [1] : _volatilityMultiplier (uint256): 1000
Arg [2] : _minOptionPricePercentage (uint256): 10000000
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [1] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [2] : 0000000000000000000000000000000000000000000000000000000000989680
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.