pragma solidity 0.5.16;
// INTERFACE
interface IERC20Mintable {
function transfer(address _to, uint256 _value) external returns (bool);
function transferFrom(
address _from,
address _to,
uint256 _value
) external returns (bool);
function mint(address _to, uint256 _value) external returns (bool);
function balanceOf(address _account) external view returns (uint256);
function totalSupply() external view returns (uint256);
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// LIB
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* _Available since v2.4.0._
*/
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*
* _Available since v2.4.0._
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-call-value
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(
value,
"SafeERC20: decreased allowance below zero"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
/**
* Smart contract library of mathematical functions operating with signed
* 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is
* basically a simple fraction whose numerator is signed 128-bit integer and
* denominator is 2^64. As long as denominator is always the same, there is no
* need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
* represented by int128 type holding only the numerator.
*/
library ABDKMath64x64 {
/*
* Minimum value signed 64.64-bit fixed point number may have.
*/
int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;
/*
* Maximum value signed 64.64-bit fixed point number may have.
*/
int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
/**
* Convert signed 256-bit integer number into signed 64.64-bit fixed point
* number. Revert on overflow.
*
* @param x signed 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function fromInt(int256 x) internal pure returns (int128) {
require(x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
return int128(x << 64);
}
/**
* Convert signed 64.64 fixed point number into signed 64-bit integer number
* rounding down.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64-bit integer number
*/
function toInt(int128 x) internal pure returns (int64) {
return int64(x >> 64);
}
/**
* Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
* number. Revert on overflow.
*
* @param x unsigned 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function fromUInt(uint256 x) internal pure returns (int128) {
require(x <= 0x7FFFFFFFFFFFFFFF);
return int128(x << 64);
}
/**
* Convert signed 64.64 fixed point number into unsigned 64-bit integer
* number rounding down. Revert on underflow.
*
* @param x signed 64.64-bit fixed point number
* @return unsigned 64-bit integer number
*/
function toUInt(int128 x) internal pure returns (uint64) {
require(x >= 0);
return uint64(x >> 64);
}
/**
* Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
* number rounding down. Revert on overflow.
*
* @param x signed 128.128-bin fixed point number
* @return signed 64.64-bit fixed point number
*/
function from128x128(int256 x) internal pure returns (int128) {
int256 result = x >> 64;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Convert signed 64.64 fixed point number into signed 128.128 fixed point
* number.
*
* @param x signed 64.64-bit fixed point number
* @return signed 128.128 fixed point number
*/
function to128x128(int128 x) internal pure returns (int256) {
return int256(x) << 64;
}
/**
* Calculate x + y. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function add(int128 x, int128 y) internal pure returns (int128) {
int256 result = int256(x) + y;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Calculate x - y. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function sub(int128 x, int128 y) internal pure returns (int128) {
int256 result = int256(x) - y;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Calculate x * y rounding down. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function mul(int128 x, int128 y) internal pure returns (int128) {
int256 result = (int256(x) * y) >> 64;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
* number and y is signed 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64 fixed point number
* @param y signed 256-bit integer number
* @return signed 256-bit integer number
*/
function muli(int128 x, int256 y) internal pure returns (int256) {
if (x == MIN_64x64) {
require(
y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
y <= 0x1000000000000000000000000000000000000000000000000
);
return -y << 63;
} else {
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y; // We rely on overflow behavior here
negativeResult = !negativeResult;
}
uint256 absoluteResult = mulu(x, uint256(y));
if (negativeResult) {
require(absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256(absoluteResult); // We rely on overflow behavior here
} else {
require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256(absoluteResult);
}
}
}
/**
* Calculate x * y rounding down, where x is signed 64.64 fixed point number
* and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64 fixed point number
* @param y unsigned 256-bit integer number
* @return unsigned 256-bit integer number
*/
function mulu(int128 x, uint256 y) internal pure returns (uint256) {
if (y == 0) return 0;
require(x >= 0);
uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
uint256 hi = uint256(x) * (y >> 128);
require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
hi <<= 64;
require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
return hi + lo;
}
/**
* Calculate x / y rounding towards zero. Revert on overflow or when y is
* zero.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function div(int128 x, int128 y) internal pure returns (int128) {
require(y != 0);
int256 result = (int256(x) << 64) / y;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Calculate x / y rounding towards zero, where x and y are signed 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x signed 256-bit integer number
* @param y signed 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function divi(int256 x, int256 y) internal pure returns (int128) {
require(y != 0);
bool negativeResult = false;
if (x < 0) {
x = -x; // We rely on overflow behavior here
negativeResult = true;
}
if (y < 0) {
y = -y; // We rely on overflow behavior here
negativeResult = !negativeResult;
}
uint128 absoluteResult = divuu(uint256(x), uint256(y));
if (negativeResult) {
require(absoluteResult <= 0x80000000000000000000000000000000);
return -int128(absoluteResult); // We rely on overflow behavior here
} else {
require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128(absoluteResult); // We rely on overflow behavior here
}
}
/**
* Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x unsigned 256-bit integer number
* @param y unsigned 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function divu(uint256 x, uint256 y) internal pure returns (int128) {
require(y != 0);
uint128 result = divuu(x, y);
require(result <= uint128(MAX_64x64));
return int128(result);
}
/**
* Calculate -x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function neg(int128 x) internal pure returns (int128) {
require(x != MIN_64x64);
return -x;
}
/**
* Calculate |x|. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function abs(int128 x) internal pure returns (int128) {
require(x != MIN_64x64);
return x < 0 ? -x : x;
}
/**
* Calculate 1 / x rounding towards zero. Revert on overflow or when x is
* zero.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function inv(int128 x) internal pure returns (int128) {
require(x != 0);
int256 result = int256(0x100000000000000000000000000000000) / x;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function avg(int128 x, int128 y) internal pure returns (int128) {
return int128((int256(x) + int256(y)) >> 1);
}
/**
* Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
* Revert on overflow or in case x * y is negative.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function gavg(int128 x, int128 y) internal pure returns (int128) {
int256 m = int256(x) * int256(y);
require(m >= 0);
require(m < 0x4000000000000000000000000000000000000000000000000000000000000000);
return int128(sqrtu(uint256(m)));
}
/**
* Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
* and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y uint256 value
* @return signed 64.64-bit fixed point number
*/
function pow(int128 x, uint256 y) internal pure returns (int128) {
bool negative = x < 0 && y & 1 == 1;
uint256 absX = uint128(x < 0 ? -x : x);
uint256 absResult;
absResult = 0x100000000000000000000000000000000;
if (absX <= 0x10000000000000000) {
absX <<= 63;
while (y != 0) {
if (y & 0x1 != 0) {
absResult = (absResult * absX) >> 127;
}
absX = (absX * absX) >> 127;
if (y & 0x2 != 0) {
absResult = (absResult * absX) >> 127;
}
absX = (absX * absX) >> 127;
if (y & 0x4 != 0) {
absResult = (absResult * absX) >> 127;
}
absX = (absX * absX) >> 127;
if (y & 0x8 != 0) {
absResult = (absResult * absX) >> 127;
}
absX = (absX * absX) >> 127;
y >>= 4;
}
absResult >>= 64;
} else {
uint256 absXShift = 63;
if (absX < 0x1000000000000000000000000) {
absX <<= 32;
absXShift -= 32;
}
if (absX < 0x10000000000000000000000000000) {
absX <<= 16;
absXShift -= 16;
}
if (absX < 0x1000000000000000000000000000000) {
absX <<= 8;
absXShift -= 8;
}
if (absX < 0x10000000000000000000000000000000) {
absX <<= 4;
absXShift -= 4;
}
if (absX < 0x40000000000000000000000000000000) {
absX <<= 2;
absXShift -= 2;
}
if (absX < 0x80000000000000000000000000000000) {
absX <<= 1;
absXShift -= 1;
}
uint256 resultShift = 0;
while (y != 0) {
require(absXShift < 64);
if (y & 0x1 != 0) {
absResult = (absResult * absX) >> 127;
resultShift += absXShift;
if (absResult > 0x100000000000000000000000000000000) {
absResult >>= 1;
resultShift += 1;
}
}
absX = (absX * absX) >> 127;
absXShift <<= 1;
if (absX >= 0x100000000000000000000000000000000) {
absX >>= 1;
absXShift += 1;
}
y >>= 1;
}
require(resultShift < 64);
absResult >>= 64 - resultShift;
}
int256 result = negative ? -int256(absResult) : int256(absResult);
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
/**
* Calculate sqrt (x) rounding down. Revert if x < 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function sqrt(int128 x) internal pure returns (int128) {
require(x >= 0);
return int128(sqrtu(uint256(x) << 64));
}
/**
* Calculate binary logarithm of x. Revert if x <= 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function log_2(int128 x) internal pure returns (int128) {
require(x > 0);
int256 msb = 0;
int256 xc = x;
if (xc >= 0x10000000000000000) {
xc >>= 64;
msb += 64;
}
if (xc >= 0x100000000) {
xc >>= 32;
msb += 32;
}
if (xc >= 0x10000) {
xc >>= 16;
msb += 16;
}
if (xc >= 0x100) {
xc >>= 8;
msb += 8;
}
if (xc >= 0x10) {
xc >>= 4;
msb += 4;
}
if (xc >= 0x4) {
xc >>= 2;
msb += 2;
}
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
int256 result = (msb - 64) << 64;
uint256 ux = uint256(x) << uint256(127 - msb);
for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
ux *= ux;
uint256 b = ux >> 255;
ux >>= 127 + b;
result += bit * int256(b);
}
return int128(result);
}
/**
* Calculate natural logarithm of x. Revert if x <= 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function ln(int128 x) internal pure returns (int128) {
require(x > 0);
return int128((uint256(log_2(x)) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF) >> 128);
}
/**
* Calculate binary exponent of x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function exp_2(int128 x) internal pure returns (int128) {
require(x < 0x400000000000000000); // Overflow
if (x < -0x400000000000000000) return 0; // Underflow
uint256 result = 0x80000000000000000000000000000000;
if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;
if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;
if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;
if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;
if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;
if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;
if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;
if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;
if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;
if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;
if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;
if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;
if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;
if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;
if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;
if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;
if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;
if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;
if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;
if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;
if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;
if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;
if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;
if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;
if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;
if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;
if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;
if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;
if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;
if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;
if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;
if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;
if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;
if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;
if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;
if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;
if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;
if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;
if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;
if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;
if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;
if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;
if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;
if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;
if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;
if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;
if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;
if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;
if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;
if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;
if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;
if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;
if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;
if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;
if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;
if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;
if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;
if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;
if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;
if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;
if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;
if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;
if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;
if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;
result >>= uint256(63 - (x >> 64));
require(result <= uint256(MAX_64x64));
return int128(result);
}
/**
* Calculate natural exponent of x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function exp(int128 x) internal pure returns (int128) {
require(x < 0x400000000000000000); // Overflow
if (x < -0x400000000000000000) return 0; // Underflow
return exp_2(int128((int256(x) * 0x171547652B82FE1777D0FFDA0D23A7D12) >> 128));
}
/**
* Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x unsigned 256-bit integer number
* @param y unsigned 256-bit integer number
* @return unsigned 64.64-bit fixed point number
*/
function divuu(uint256 x, uint256 y) private pure returns (uint128) {
require(y != 0);
uint256 result;
if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;
else {
uint256 msb = 192;
uint256 xc = x >> 192;
if (xc >= 0x100000000) {
xc >>= 32;
msb += 32;
}
if (xc >= 0x10000) {
xc >>= 16;
msb += 16;
}
if (xc >= 0x100) {
xc >>= 8;
msb += 8;
}
if (xc >= 0x10) {
xc >>= 4;
msb += 4;
}
if (xc >= 0x4) {
xc >>= 2;
msb += 2;
}
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);
require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 hi = result * (y >> 128);
uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 xh = x >> 192;
uint256 xl = x << 64;
if (xl < lo) xh -= 1;
xl -= lo; // We rely on overflow behavior here
lo = hi << 128;
if (xl < lo) xh -= 1;
xl -= lo; // We rely on overflow behavior here
assert(xh == hi >> 128);
result += xl / y;
}
require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128(result);
}
/**
* Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
* number.
*
* @param x unsigned 256-bit integer number
* @return unsigned 128-bit integer number
*/
function sqrtu(uint256 x) private pure returns (uint128) {
if (x == 0) return 0;
else {
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) {
xx >>= 128;
r <<= 64;
}
if (xx >= 0x10000000000000000) {
xx >>= 64;
r <<= 32;
}
if (xx >= 0x100000000) {
xx >>= 32;
r <<= 16;
}
if (xx >= 0x10000) {
xx >>= 16;
r <<= 8;
}
if (xx >= 0x100) {
xx >>= 8;
r <<= 4;
}
if (xx >= 0x10) {
xx >>= 4;
r <<= 2;
}
if (xx >= 0x8) {
r <<= 1;
}
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1; // Seven iterations should be enough
uint256 r1 = x / r;
return uint128(r < r1 ? r : r1);
}
}
}
/**
* Smart contract library of mathematical functions operating with IEEE 754
* quadruple-precision binary floating-point numbers (quadruple precision
* numbers). As long as quadruple precision numbers are 16-bytes long, they are
* represented by bytes16 type.
*/
library ABDKMathQuad {
/*
* 0.
*/
bytes16 private constant POSITIVE_ZERO = 0x00000000000000000000000000000000;
/*
* -0.
*/
bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000;
/*
* +Infinity.
*/
bytes16 private constant POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000;
/*
* -Infinity.
*/
bytes16 private constant NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000;
/*
* Canonical NaN value.
*/
bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;
/**
* Convert signed 256-bit integer number into quadruple precision number.
*
* @param x signed 256-bit integer number
* @return quadruple precision number
*/
function fromInt(int256 x) internal pure returns (bytes16) {
if (x == 0) return bytes16(0);
else {
// We rely on overflow behavior here
uint256 result = uint256(x > 0 ? x : -x);
uint256 msb = msb(result);
if (msb < 112) result <<= 112 - msb;
else if (msb > 112) result >>= msb - 112;
result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16383 + msb) << 112);
if (x < 0) result |= 0x80000000000000000000000000000000;
return bytes16(uint128(result));
}
}
/**
* Convert quadruple precision number into signed 256-bit integer number
* rounding towards zero. Revert on overflow.
*
* @param x quadruple precision number
* @return signed 256-bit integer number
*/
function toInt(bytes16 x) internal pure returns (int256) {
uint256 exponent = (uint128(x) >> 112) & 0x7FFF;
require(exponent <= 16638); // Overflow
if (exponent < 16383) return 0; // Underflow
uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000;
if (exponent < 16495) result >>= 16495 - exponent;
else if (exponent > 16495) result <<= exponent - 16495;
if (uint128(x) >= 0x80000000000000000000000000000000) {
// Negative
require(result <= 0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256(result); // We rely on overflow behavior here
} else {
require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256(result);
}
}
/**
* Convert unsigned 256-bit integer number into quadruple precision number.
*
* @param x unsigned 256-bit integer number
* @return quadruple precision number
*/
function fromUInt(uint256 x) internal pure returns (bytes16) {
if (x == 0) return bytes16(0);
else {
uint256 result = x;
uint256 msb = msb(result);
if (msb < 112) result <<= 112 - msb;
else if (msb > 112) result >>= msb - 112;
result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16383 + msb) << 112);
return bytes16(uint128(result));
}
}
/**
* Convert quadruple precision number into unsigned 256-bit integer number
* rounding towards zero. Revert on underflow. Note, that negative floating
* point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer
* without error, because they are rounded to zero.
*
* @param x quadruple precision number
* @return unsigned 256-bit integer number
*/
function toUInt(bytes16 x) internal pure returns (uint256) {
uint256 exponent = (uint128(x) >> 112) & 0x7FFF;
if (exponent < 16383) return 0; // Underflow
require(uint128(x) < 0x80000000000000000000000000000000); // Negative
require(exponent <= 16638); // Overflow
uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000;
if (exponent < 16495) result >>= 16495 - exponent;
else if (exponent > 16495) result <<= exponent - 16495;
return result;
}
/**
* Convert signed 128.128 bit fixed point number into quadruple precision
* number.
*
* @param x signed 128.128 bit fixed point number
* @return quadruple precision number
*/
function from128x128(int256 x) internal pure returns (bytes16) {
if (x == 0) return bytes16(0);
else {
// We rely on overflow behavior here
uint256 result = uint256(x > 0 ? x : -x);
uint256 msb = msb(result);
if (msb < 112) result <<= 112 - msb;
else if (msb > 112) result >>= msb - 112;
result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16255 + msb) << 112);
if (x < 0) result |= 0x80000000000000000000000000000000;
return bytes16(uint128(result));
}
}
/**
* Convert quadruple precision number into signed 128.128 bit fixed point
* number. Revert on overflow.
*
* @param x quadruple precision number
* @return signed 128.128 bit fixed point number
*/
function to128x128(bytes16 x) internal pure returns (int256) {
uint256 exponent = (uint128(x) >> 112) & 0x7FFF;
require(exponent <= 16510); // Overflow
if (exponent < 16255) return 0; // Underflow
uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000;
if (exponent < 16367) result >>= 16367 - exponent;
else if (exponent > 16367) result <<= exponent - 16367;
if (uint128(x) >= 0x80000000000000000000000000000000) {
// Negative
require(result <= 0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256(result); // We rely on overflow behavior here
} else {
require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256(result);
}
}
/**
* Convert signed 64.64 bit fixed point number into quadruple precision
* number.
*
* @param x signed 64.64 bit fixed point number
* @return quadruple precision number
*/
function from64x64(int128 x) internal pure returns (bytes16) {
if (x == 0) return bytes16(0);
else {
// We rely on overflow behavior here
uint256 result = uint128(x > 0 ? x : -x);
uint256 msb = msb(result);
if (msb < 112) result <<= 112 - msb;
else if (msb > 112) result >>= msb - 112;
result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16319 + msb) << 112);
if (x < 0) result |= 0x80000000000000000000000000000000;
return bytes16(uint128(result));
}
}
/**
* Convert quadruple precision number into signed 64.64 bit fixed point
* number. Revert on overflow.
*
* @param x quadruple precision number
* @return signed 64.64 bit fixed point number
*/
function to64x64(bytes16 x) internal pure returns (int128) {
uint256 exponent = (uint128(x) >> 112) & 0x7FFF;
require(exponent <= 16446); // Overflow
if (exponent < 16319) return 0; // Underflow
uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000;
if (exponent < 16431) result >>= 16431 - exponent;
else if (exponent > 16431) result <<= exponent - 16431;
if (uint128(x) >= 0x80000000000000000000000000000000) {
// Negative
require(result <= 0x80000000000000000000000000000000);
return -int128(result); // We rely on overflow behavior here
} else {
require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128(result);
}
}
/**
* Convert octuple precision number into quadruple precision number.
*
* @param x octuple precision number
* @return quadruple precision number
*/
function fromOctuple(bytes32 x) internal pure returns (bytes16) {
bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0;
uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;
uint256 significand = uint256(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (exponent == 0x7FFFF) {
if (significand > 0) return NaN;
else return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
}
if (exponent > 278526) return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
else if (exponent < 245649) return negative ? NEGATIVE_ZERO : POSITIVE_ZERO;
else if (exponent < 245761) {
significand =
(significand | 0x100000000000000000000000000000000000000000000000000000000000) >>
(245885 - exponent);
exponent = 0;
} else {
significand >>= 124;
exponent -= 245760;
}
uint128 result = uint128(significand | (exponent << 112));
if (negative) result |= 0x80000000000000000000000000000000;
return bytes16(result);
}
/**
* Convert quadruple precision number into octuple precision number.
*
* @param x quadruple precision number
* @return octuple precision number
*/
function toOctuple(bytes16 x) internal pure returns (bytes32) {
uint256 exponent = (uint128(x) >> 112) & 0x7FFF;
uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (exponent == 0x7FFF)
exponent = 0x7FFFF; // Infinity or NaN
else if (exponent == 0) {
if (result > 0) {
uint256 msb = msb(result);
result = (result << (236 - msb)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
exponent = 245649 + msb;
}
} else {
result <<= 124;
exponent += 245760;
}
result |= exponent << 236;
if (uint128(x) >= 0x80000000000000000000000000000000)
result |= 0x8000000000000000000000000000000000000000000000000000000000000000;
return bytes32(result);
}
/**
* Convert double precision number into quadruple precision number.
*
* @param x double precision number
* @return quadruple precision number
*/
function fromDouble(bytes8 x) internal pure returns (bytes16) {
uint256 exponent = (uint64(x) >> 52) & 0x7FF;
uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;
if (exponent == 0x7FF)
exponent = 0x7FFF; // Infinity or NaN
else if (exponent == 0) {
if (result > 0) {
uint256 msb = msb(result);
result = (result << (112 - msb)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
exponent = 15309 + msb;
}
} else {
result <<= 60;
exponent += 15360;
}
result |= exponent << 112;
if (x & 0x8000000000000000 > 0) result |= 0x80000000000000000000000000000000;
return bytes16(uint128(result));
}
/**
* Convert quadruple precision number into double precision number.
*
* @param x quadruple precision number
* @return double precision number
*/
function toDouble(bytes16 x) internal pure returns (bytes8) {
bool negative = uint128(x) >= 0x80000000000000000000000000000000;
uint256 exponent = (uint128(x) >> 112) & 0x7FFF;
uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (exponent == 0x7FFF) {
if (significand > 0) return 0x7FF8000000000000;
// NaN
else
return
negative
? bytes8(0xFFF0000000000000) // -Infinity
: bytes8(0x7FF0000000000000); // Infinity
}
if (exponent > 17406)
return
negative
? bytes8(0xFFF0000000000000) // -Infinity
: bytes8(0x7FF0000000000000);
// Infinity
else if (exponent < 15309)
return
negative
? bytes8(0x8000000000000000) // -0
: bytes8(0x0000000000000000);
// 0
else if (exponent < 15361) {
significand = (significand | 0x10000000000000000000000000000) >> (15421 - exponent);
exponent = 0;
} else {
significand >>= 60;
exponent -= 15360;
}
uint64 result = uint64(significand | (exponent << 52));
if (negative) result |= 0x8000000000000000;
return bytes8(result);
}
/**
* Test whether given quadruple precision number is NaN.
*
* @param x quadruple precision number
* @return true if x is NaN, false otherwise
*/
function isNaN(bytes16 x) internal pure returns (bool) {
return uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > 0x7FFF0000000000000000000000000000;
}
/**
* Test whether given quadruple precision number is positive or negative
* infinity.
*
* @param x quadruple precision number
* @return true if x is positive or negative infinity, false otherwise
*/
function isInfinity(bytes16 x) internal pure returns (bool) {
return uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x7FFF0000000000000000000000000000;
}
/**
* Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x
* is positive. Note that sign (-0) is zero. Revert if x is NaN.
*
* @param x quadruple precision number
* @return sign of x
*/
function sign(bytes16 x) internal pure returns (int8) {
uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN
if (absoluteX == 0) return 0;
else if (uint128(x) >= 0x80000000000000000000000000000000) return -1;
else return 1;
}
/**
* Calculate sign (x - y). Revert if either argument is NaN, or both
* arguments are infinities of the same sign.
*
* @param x quadruple precision number
* @param y quadruple precision number
* @return sign (x - y)
*/
function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {
uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN
uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN
// Not infinities of the same sign
require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);
if (x == y) return 0;
else {
bool negativeX = uint128(x) >= 0x80000000000000000000000000000000;
bool negativeY = uint128(y) >= 0x80000000000000000000000000000000;
if (negativeX) {
if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);
else return -1;
} else {
if (negativeY) return 1;
else return absoluteX > absoluteY ? int8(1) : -1;
}
}
}
/**
* Test whether x equals y. NaN, infinity, and -infinity are not equal to
* anything.
*
* @param x quadruple precision number
* @param y quadruple precision number
* @return true if x equals to y, false otherwise
*/
function eq(bytes16 x, bytes16 y) internal pure returns (bool) {
if (x == y) {
return uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF < 0x7FFF0000000000000000000000000000;
} else return false;
}
/**
* Calculate x + y. Special values behave in the following way:
*
* NaN + x = NaN for any x.
* Infinity + x = Infinity for any finite x.
* -Infinity + x = -Infinity for any finite x.
* Infinity + Infinity = Infinity.
* -Infinity + -Infinity = -Infinity.
* Infinity + -Infinity = -Infinity + Infinity = NaN.
*
* @param x quadruple precision number
* @param y quadruple precision number
* @return quadruple precision number
*/
function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {
uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;
uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;
if (xExponent == 0x7FFF) {
if (yExponent == 0x7FFF) {
if (x == y) return x;
else return NaN;
} else return x;
} else if (yExponent == 0x7FFF) return y;
else {
bool xSign = uint128(x) >= 0x80000000000000000000000000000000;
uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0) xExponent = 1;
else xSignifier |= 0x10000000000000000000000000000;
bool ySign = uint128(y) >= 0x80000000000000000000000000000000;
uint256 ySignifier = uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (yExponent == 0) yExponent = 1;
else ySignifier |= 0x10000000000000000000000000000;
if (xSignifier == 0) return y == NEGATIVE_ZERO ? POSITIVE_ZERO : y;
else if (ySignifier == 0) return x == NEGATIVE_ZERO ? POSITIVE_ZERO : x;
else {
int256 delta = int256(xExponent) - int256(yExponent);
if (xSign == ySign) {
if (delta > 112) return x;
else if (delta > 0) ySignifier >>= uint256(delta);
else if (delta < -112) return y;
else if (delta < 0) {
xSignifier >>= uint256(-delta);
xExponent = yExponent;
}
xSignifier += ySignifier;
if (xSignifier >= 0x20000000000000000000000000000) {
xSignifier >>= 1;
xExponent += 1;
}
if (xExponent == 0x7FFF) return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
else {
if (xSignifier < 0x10000000000000000000000000000) xExponent = 0;
else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
return
bytes16(
uint128(
(xSign ? 0x80000000000000000000000000000000 : 0) | (xExponent << 112) | xSignifier
)
);
}
} else {
if (delta > 0) {
xSignifier <<= 1;
xExponent -= 1;
} else if (delta < 0) {
ySignifier <<= 1;
xExponent = yExponent - 1;
}
if (delta > 112) ySignifier = 1;
else if (delta > 1) ySignifier = ((ySignifier - 1) >> uint256(delta - 1)) + 1;
else if (delta < -112) xSignifier = 1;
else if (delta < -1) xSignifier = ((xSignifier - 1) >> uint256(-delta - 1)) + 1;
if (xSignifier >= ySignifier) xSignifier -= ySignifier;
else {
xSignifier = ySignifier - xSignifier;
xSign = ySign;
}
if (xSignifier == 0) return POSITIVE_ZERO;
uint256 msb = msb(xSignifier);
if (msb == 113) {
xSignifier = (xSignifier >> 1) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
xExponent += 1;
} else if (msb < 112) {
uint256 shift = 112 - msb;
if (xExponent > shift) {
xSignifier = (xSignifier << shift) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
xExponent -= shift;
} else {
xSignifier <<= xExponent - 1;
xExponent = 0;
}
} else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0x7FFF) return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
else
return
bytes16(
uint128(
(xSign ? 0x80000000000000000000000000000000 : 0) | (xExponent << 112) | xSignifier
)
);
}
}
}
}
/**
* Calculate x - y. Special values behave in the following way:
*
* NaN - x = NaN for any x.
* Infinity - x = Infinity for any finite x.
* -Infinity - x = -Infinity for any finite x.
* Infinity - -Infinity = Infinity.
* -Infinity - Infinity = -Infinity.
* Infinity - Infinity = -Infinity - -Infinity = NaN.
*
* @param x quadruple precision number
* @param y quadruple precision number
* @return quadruple precision number
*/
function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {
return add(x, y ^ 0x80000000000000000000000000000000);
}
/**
* Calculate x * y. Special values behave in the following way:
*
* NaN * x = NaN for any x.
* Infinity * x = Infinity for any finite positive x.
* Infinity * x = -Infinity for any finite negative x.
* -Infinity * x = -Infinity for any finite positive x.
* -Infinity * x = Infinity for any finite negative x.
* Infinity * 0 = NaN.
* -Infinity * 0 = NaN.
* Infinity * Infinity = Infinity.
* Infinity * -Infinity = -Infinity.
* -Infinity * Infinity = -Infinity.
* -Infinity * -Infinity = Infinity.
*
* @param x quadruple precision number
* @param y quadruple precision number
* @return quadruple precision number
*/
function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {
uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;
uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;
if (xExponent == 0x7FFF) {
if (yExponent == 0x7FFF) {
if (x == y) return x ^ (y & 0x80000000000000000000000000000000);
else if (x ^ y == 0x80000000000000000000000000000000) return x | y;
else return NaN;
} else {
if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
else return x ^ (y & 0x80000000000000000000000000000000);
}
} else if (yExponent == 0x7FFF) {
if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
else return y ^ (x & 0x80000000000000000000000000000000);
} else {
uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0) xExponent = 1;
else xSignifier |= 0x10000000000000000000000000000;
uint256 ySignifier = uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (yExponent == 0) yExponent = 1;
else ySignifier |= 0x10000000000000000000000000000;
xSignifier *= ySignifier;
if (xSignifier == 0)
return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? NEGATIVE_ZERO : POSITIVE_ZERO;
xExponent += yExponent;
uint256 msb = xSignifier >= 0x200000000000000000000000000000000000000000000000000000000
? 225
: xSignifier >= 0x100000000000000000000000000000000000000000000000000000000
? 224
: msb(xSignifier);
if (xExponent + msb < 16496) {
// Underflow
xExponent = 0;
xSignifier = 0;
} else if (xExponent + msb < 16608) {
// Subnormal
if (xExponent < 16496) xSignifier >>= 16496 - xExponent;
else if (xExponent > 16496) xSignifier <<= xExponent - 16496;
xExponent = 0;
} else if (xExponent + msb > 49373) {
xExponent = 0x7FFF;
xSignifier = 0;
} else {
if (msb > 112) xSignifier >>= msb - 112;
else if (msb < 112) xSignifier <<= 112 - msb;
xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
xExponent = xExponent + msb - 16607;
}
return
bytes16(
uint128(uint128((x ^ y) & 0x80000000000000000000000000000000) | (xExponent << 112) | xSignifier)
);
}
}
/**
* Calculate x / y. Special values behave in the following way:
*
* NaN / x = NaN for any x.
* x / NaN = NaN for any x.
* Infinity / x = Infinity for any finite non-negative x.
* Infinity / x = -Infinity for any finite negative x including -0.
* -Infinity / x = -Infinity for any finite non-negative x.
* -Infinity / x = Infinity for any finite negative x including -0.
* x / Infinity = 0 for any finite non-negative x.
* x / -Infinity = -0 for any finite non-negative x.
* x / Infinity = -0 for any finite non-negative x including -0.
* x / -Infinity = 0 for any finite non-negative x including -0.
*
* Infinity / Infinity = NaN.
* Infinity / -Infinity = -NaN.
* -Infinity / Infinity = -NaN.
* -Infinity / -Infinity = NaN.
*
* Division by zero behaves in the following way:
*
* x / 0 = Infinity for any finite positive x.
* x / -0 = -Infinity for any finite positive x.
* x / 0 = -Infinity for any finite negative x.
* x / -0 = Infinity for any finite negative x.
* 0 / 0 = NaN.
* 0 / -0 = NaN.
* -0 / 0 = NaN.
* -0 / -0 = NaN.
*
* @param x quadruple precision number
* @param y quadruple precision number
* @return quadruple precision number
*/
function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {
uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;
uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;
if (xExponent == 0x7FFF) {
if (yExponent == 0x7FFF) return NaN;
else return x ^ (y & 0x80000000000000000000000000000000);
} else if (yExponent == 0x7FFF) {
if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;
else return POSITIVE_ZERO | ((x ^ y) & 0x80000000000000000000000000000000);
} else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {
if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
else return POSITIVE_INFINITY | ((x ^ y) & 0x80000000000000000000000000000000);
} else {
uint256 ySignifier = uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (yExponent == 0) yExponent = 1;
else ySignifier |= 0x10000000000000000000000000000;
uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0) {
if (xSignifier != 0) {
uint256 shift = 226 - msb(xSignifier);
xSignifier <<= shift;
xExponent = 1;
yExponent += shift - 114;
}
} else {
xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114;
}
xSignifier = xSignifier / ySignifier;
if (xSignifier == 0)
return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? NEGATIVE_ZERO : POSITIVE_ZERO;
assert(xSignifier >= 0x1000000000000000000000000000);
uint256 msb = xSignifier >= 0x80000000000000000000000000000
? msb(xSignifier)
: xSignifier >= 0x40000000000000000000000000000
? 114
: xSignifier >= 0x20000000000000000000000000000
? 113
: 112;
if (xExponent + msb > yExponent + 16497) {
// Overflow
xExponent = 0x7FFF;
xSignifier = 0;
} else if (xExponent + msb + 16380 < yExponent) {
// Underflow
xExponent = 0;
xSignifier = 0;
} else if (xExponent + msb + 16268 < yExponent) {
// Subnormal
if (xExponent + 16380 > yExponent) xSignifier <<= xExponent + 16380 - yExponent;
else if (xExponent + 16380 < yExponent) xSignifier >>= yExponent - xExponent - 16380;
xExponent = 0;
} else {
// Normal
if (msb > 112) xSignifier >>= msb - 112;
xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
xExponent = xExponent + msb + 16269 - yExponent;
}
return
bytes16(
uint128(uint128((x ^ y) & 0x80000000000000000000000000000000) | (xExponent << 112) | xSignifier)
);
}
}
/**
* Calculate -x.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function neg(bytes16 x) internal pure returns (bytes16) {
return x ^ 0x80000000000000000000000000000000;
}
/**
* Calculate |x|.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function abs(bytes16 x) internal pure returns (bytes16) {
return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
}
/**
* Calculate square root of x. Return NaN on negative x excluding -0.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function sqrt(bytes16 x) internal pure returns (bytes16) {
if (uint128(x) > 0x80000000000000000000000000000000) return NaN;
else {
uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;
if (xExponent == 0x7FFF) return x;
else {
uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0) xExponent = 1;
else xSignifier |= 0x10000000000000000000000000000;
if (xSignifier == 0) return POSITIVE_ZERO;
bool oddExponent = xExponent & 0x1 == 0;
xExponent = (xExponent + 16383) >> 1;
if (oddExponent) {
if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 113;
else {
uint256 msb = msb(xSignifier);
uint256 shift = (226 - msb) & 0xFE;
xSignifier <<= shift;
xExponent -= (shift - 112) >> 1;
}
} else {
if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 112;
else {
uint256 msb = msb(xSignifier);
uint256 shift = (225 - msb) & 0xFE;
xSignifier <<= shift;
xExponent -= (shift - 112) >> 1;
}
}
uint256 r = 0x10000000000000000000000000000;
r = (r + xSignifier / r) >> 1;
r = (r + xSignifier / r) >> 1;
r = (r + xSignifier / r) >> 1;
r = (r + xSignifier / r) >> 1;
r = (r + xSignifier / r) >> 1;
r = (r + xSignifier / r) >> 1;
r = (r + xSignifier / r) >> 1; // Seven iterations should be enough
uint256 r1 = xSignifier / r;
if (r1 < r) r = r1;
return bytes16(uint128((xExponent << 112) | (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
}
}
}
/**
* Calculate binary logarithm of x. Return NaN on negative x excluding -0.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function log_2(bytes16 x) internal pure returns (bytes16) {
if (uint128(x) > 0x80000000000000000000000000000000) return NaN;
else if (x == 0x3FFF0000000000000000000000000000) return POSITIVE_ZERO;
else {
uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;
if (xExponent == 0x7FFF) return x;
else {
uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0) xExponent = 1;
else xSignifier |= 0x10000000000000000000000000000;
if (xSignifier == 0) return NEGATIVE_INFINITY;
bool resultNegative;
uint256 resultExponent = 16495;
uint256 resultSignifier;
if (xExponent >= 0x3FFF) {
resultNegative = false;
resultSignifier = xExponent - 0x3FFF;
xSignifier <<= 15;
} else {
resultNegative = true;
if (xSignifier >= 0x10000000000000000000000000000) {
resultSignifier = 0x3FFE - xExponent;
xSignifier <<= 15;
} else {
uint256 msb = msb(xSignifier);
resultSignifier = 16493 - msb;
xSignifier <<= 127 - msb;
}
}
if (xSignifier == 0x80000000000000000000000000000000) {
if (resultNegative) resultSignifier += 1;
uint256 shift = 112 - msb(resultSignifier);
resultSignifier <<= shift;
resultExponent -= shift;
} else {
uint256 bb = resultNegative ? 1 : 0;
while (resultSignifier < 0x10000000000000000000000000000) {
resultSignifier <<= 1;
resultExponent -= 1;
xSignifier *= xSignifier;
uint256 b = xSignifier >> 255;
resultSignifier += b ^ bb;
xSignifier >>= 127 + b;
}
}
return
bytes16(
uint128(
(resultNegative ? 0x80000000000000000000000000000000 : 0) |
(resultExponent << 112) |
(resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
)
);
}
}
}
/**
* Calculate natural logarithm of x. Return NaN on negative x excluding -0.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function ln(bytes16 x) internal pure returns (bytes16) {
return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);
}
/**
* Calculate 2^x.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function pow_2(bytes16 x) internal pure returns (bytes16) {
bool xNegative = uint128(x) > 0x80000000000000000000000000000000;
uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;
uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xExponent == 0x7FFF && xSignifier != 0) return NaN;
else if (xExponent > 16397) return xNegative ? POSITIVE_ZERO : POSITIVE_INFINITY;
else if (xExponent < 16255) return 0x3FFF0000000000000000000000000000;
else {
if (xExponent == 0) xExponent = 1;
else xSignifier |= 0x10000000000000000000000000000;
if (xExponent > 16367) xSignifier <<= xExponent - 16367;
else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;
if (xNegative && xSignifier > 0x406E00000000000000000000000000000000) return POSITIVE_ZERO;
if (!xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) return POSITIVE_INFINITY;
uint256 resultExponent = xSignifier >> 128;
xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if (xNegative && xSignifier != 0) {
xSignifier = ~xSignifier;
resultExponent += 1;
}
uint256 resultSignifier = 0x80000000000000000000000000000000;
if (xSignifier & 0x80000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;
if (xSignifier & 0x40000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;
if (xSignifier & 0x20000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;
if (xSignifier & 0x10000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10B5586CF9890F6298B92B71842A98363) >> 128;
if (xSignifier & 0x8000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;
if (xSignifier & 0x4000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;
if (xSignifier & 0x2000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;
if (xSignifier & 0x1000000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;
if (xSignifier & 0x800000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;
if (xSignifier & 0x400000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;
if (xSignifier & 0x200000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;
if (xSignifier & 0x100000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;
if (xSignifier & 0x80000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;
if (xSignifier & 0x40000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;
if (xSignifier & 0x20000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000162E525EE054754457D5995292026) >> 128;
if (xSignifier & 0x10000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;
if (xSignifier & 0x8000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;
if (xSignifier & 0x4000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;
if (xSignifier & 0x2000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000162E43F4F831060E02D839A9D16D) >> 128;
if (xSignifier & 0x1000000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000B1721BCFC99D9F890EA06911763) >> 128;
if (xSignifier & 0x800000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;
if (xSignifier & 0x400000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;
if (xSignifier & 0x200000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000162E430E5A18F6119E3C02282A5) >> 128;
if (xSignifier & 0x100000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;
if (xSignifier & 0x80000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;
if (xSignifier & 0x40000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;
if (xSignifier & 0x20000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;
if (xSignifier & 0x10000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;
if (xSignifier & 0x8000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;
if (xSignifier & 0x4000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;
if (xSignifier & 0x2000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;
if (xSignifier & 0x1000000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000B17217F80F4EF5AADDA45554) >> 128;
if (xSignifier & 0x800000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;
if (xSignifier & 0x400000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;
if (xSignifier & 0x200000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000162E42FEFB2FED257559BDAA) >> 128;
if (xSignifier & 0x100000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;
if (xSignifier & 0x80000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;
if (xSignifier & 0x40000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;
if (xSignifier & 0x20000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000162E42FEFA494F1478FDE05) >> 128;
if (xSignifier & 0x10000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000B17217F7D20CF927C8E94C) >> 128;
if (xSignifier & 0x8000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;
if (xSignifier & 0x4000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000002C5C85FDF477B662B26945) >> 128;
if (xSignifier & 0x2000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000162E42FEFA3AE53369388C) >> 128;
if (xSignifier & 0x1000000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000B17217F7D1D351A389D40) >> 128;
if (xSignifier & 0x800000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;
if (xSignifier & 0x400000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;
if (xSignifier & 0x200000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000162E42FEFA39FE95583C2) >> 128;
if (xSignifier & 0x100000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;
if (xSignifier & 0x80000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;
if (xSignifier & 0x40000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000002C5C85FDF473E242EA38) >> 128;
if (xSignifier & 0x20000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000162E42FEFA39F02B772C) >> 128;
if (xSignifier & 0x10000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;
if (xSignifier & 0x8000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;
if (xSignifier & 0x4000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000002C5C85FDF473DEA871F) >> 128;
if (xSignifier & 0x2000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000162E42FEFA39EF44D91) >> 128;
if (xSignifier & 0x1000000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000B17217F7D1CF79E949) >> 128;
if (xSignifier & 0x800000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000058B90BFBE8E7BCE544) >> 128;
if (xSignifier & 0x400000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;
if (xSignifier & 0x200000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000162E42FEFA39EF366F) >> 128;
if (xSignifier & 0x100000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000B17217F7D1CF79AFA) >> 128;
if (xSignifier & 0x80000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;
if (xSignifier & 0x40000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000002C5C85FDF473DE6B2) >> 128;
if (xSignifier & 0x20000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000162E42FEFA39EF358) >> 128;
if (xSignifier & 0x10000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000B17217F7D1CF79AB) >> 128;
if (xSignifier & 0x8000000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5) >> 128;
if (xSignifier & 0x4000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000002C5C85FDF473DE6A) >> 128;
if (xSignifier & 0x2000000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000162E42FEFA39EF34) >> 128;
if (xSignifier & 0x1000000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000B17217F7D1CF799) >> 128;
if (xSignifier & 0x800000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000058B90BFBE8E7BCC) >> 128;
if (xSignifier & 0x400000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000002C5C85FDF473DE5) >> 128;
if (xSignifier & 0x200000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000162E42FEFA39EF2) >> 128;
if (xSignifier & 0x100000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000B17217F7D1CF78) >> 128;
if (xSignifier & 0x80000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000058B90BFBE8E7BB) >> 128;
if (xSignifier & 0x40000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000002C5C85FDF473DD) >> 128;
if (xSignifier & 0x20000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000162E42FEFA39EE) >> 128;
if (xSignifier & 0x10000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000B17217F7D1CF6) >> 128;
if (xSignifier & 0x8000000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000058B90BFBE8E7A) >> 128;
if (xSignifier & 0x4000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000002C5C85FDF473C) >> 128;
if (xSignifier & 0x2000000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000162E42FEFA39D) >> 128;
if (xSignifier & 0x1000000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000B17217F7D1CE) >> 128;
if (xSignifier & 0x800000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000058B90BFBE8E6) >> 128;
if (xSignifier & 0x400000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000002C5C85FDF472) >> 128;
if (xSignifier & 0x200000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000162E42FEFA38) >> 128;
if (xSignifier & 0x100000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000B17217F7D1B) >> 128;
if (xSignifier & 0x80000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000058B90BFBE8D) >> 128;
if (xSignifier & 0x40000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000002C5C85FDF46) >> 128;
if (xSignifier & 0x20000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000162E42FEFA2) >> 128;
if (xSignifier & 0x10000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000B17217F7D0) >> 128;
if (xSignifier & 0x8000000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000058B90BFBE7) >> 128;
if (xSignifier & 0x4000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000002C5C85FDF3) >> 128;
if (xSignifier & 0x2000000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000162E42FEF9) >> 128;
if (xSignifier & 0x1000000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000B17217F7C) >> 128;
if (xSignifier & 0x800000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000058B90BFBD) >> 128;
if (xSignifier & 0x400000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000002C5C85FDE) >> 128;
if (xSignifier & 0x200000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000162E42FEE) >> 128;
if (xSignifier & 0x100000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000B17217F6) >> 128;
if (xSignifier & 0x80000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000058B90BFA) >> 128;
if (xSignifier & 0x40000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000002C5C85FC) >> 128;
if (xSignifier & 0x20000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000162E42FD) >> 128;
if (xSignifier & 0x10000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000B17217E) >> 128;
if (xSignifier & 0x8000000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000058B90BE) >> 128;
if (xSignifier & 0x4000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000002C5C85E) >> 128;
if (xSignifier & 0x2000000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000162E42E) >> 128;
if (xSignifier & 0x1000000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000000B17216) >> 128;
if (xSignifier & 0x800000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000058B90A) >> 128;
if (xSignifier & 0x400000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000002C5C84) >> 128;
if (xSignifier & 0x200000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000000162E41) >> 128;
if (xSignifier & 0x100000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000000B1720) >> 128;
if (xSignifier & 0x80000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000000058B8F) >> 128;
if (xSignifier & 0x40000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000002C5C7) >> 128;
if (xSignifier & 0x20000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000000162E3) >> 128;
if (xSignifier & 0x10000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000000B171) >> 128;
if (xSignifier & 0x8000 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000000058B8) >> 128;
if (xSignifier & 0x4000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000000002C5B) >> 128;
if (xSignifier & 0x2000 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000000162D) >> 128;
if (xSignifier & 0x1000 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000000000B16) >> 128;
if (xSignifier & 0x800 > 0)
resultSignifier = (resultSignifier * 0x10000000000000000000000000000058A) >> 128;
if (xSignifier & 0x400 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000000002C4) >> 128;
if (xSignifier & 0x200 > 0)
resultSignifier = (resultSignifier * 0x100000000000000000000000000000161) >> 128;
if (xSignifier & 0x100 > 0)
resultSignifier = (resultSignifier * 0x1000000000000000000000000000000B0) >> 128;
if (xSignifier & 0x80 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000057) >> 128;
if (xSignifier & 0x40 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000002B) >> 128;
if (xSignifier & 0x20 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000015) >> 128;
if (xSignifier & 0x10 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000000A) >> 128;
if (xSignifier & 0x8 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000004) >> 128;
if (xSignifier & 0x4 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000001) >> 128;
if (!xNegative) {
resultSignifier = (resultSignifier >> 15) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
resultExponent += 0x3FFF;
} else if (resultExponent <= 0x3FFE) {
resultSignifier = (resultSignifier >> 15) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
resultExponent = 0x3FFF - resultExponent;
} else {
resultSignifier = resultSignifier >> (resultExponent - 16367);
resultExponent = 0;
}
return bytes16(uint128((resultExponent << 112) | resultSignifier));
}
}
/**
* Calculate e^x.
*
* @param x quadruple precision number
* @return quadruple precision number
*/
function exp(bytes16 x) internal pure returns (bytes16) {
return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));
}
/**
* Get index of the most significant non-zero bit in binary representation of
* x. Reverts if x is zero.
*
* @return index of the most significant non-zero bit in binary representation
* of x
*/
function msb(uint256 x) private pure returns (uint256) {
require(x > 0);
uint256 result = 0;
if (x >= 0x100000000000000000000000000000000) {
x >>= 128;
result += 128;
}
if (x >= 0x10000000000000000) {
x >>= 64;
result += 64;
}
if (x >= 0x100000000) {
x >>= 32;
result += 32;
}
if (x >= 0x10000) {
x >>= 16;
result += 16;
}
if (x >= 0x100) {
x >>= 8;
result += 8;
}
if (x >= 0x10) {
x >>= 4;
result += 4;
}
if (x >= 0x4) {
x >>= 2;
result += 2;
}
if (x >= 0x2) result += 1; // No need to shift x anymore
return result;
}
}
// CONTRACTS
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(
initializing || isConstructor() || !initialized,
"Contract instance has already been initialized"
);
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly {
cs := extcodesize(self)
}
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}
contract Sacrifice {
constructor(address payable _recipient) public payable {
selfdestruct(_recipient);
}
}
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*/
contract ReentrancyGuard is Initializable {
// counter to allow mutex lock with only one SSTORE operation
uint256 private _guardCounter;
function initialize() public initializer {
// The counter starts at one to prevent changing it from zero to a non-zero
// value, which is a more expensive operation.
_guardCounter = 1;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_guardCounter += 1;
uint256 localCounter = _guardCounter;
_;
require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
}
uint256[50] private ______gap;
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public view returns (uint256);
function balanceOf(address tokenOwner) public view returns (uint256 balance);
function allowance(address tokenOwner, address spender) public view returns (uint256 remaining);
function transfer(address to, uint256 tokens) public returns (bool success);
function approve(address spender, uint256 tokens) public returns (bool success);
function transferFrom(
address from,
address to,
uint256 tokens
) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint256 tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint256 tokens);
}
// ----------------------------------------------------------------------------
// Safe Math Library
// ----------------------------------------------------------------------------
contract SafeMathERC20 {
function safeAdd(uint256 a, uint256 b) public pure returns (uint256 c) {
c = a + b;
require(c >= a);
}
function safeSub(uint256 a, uint256 b) public pure returns (uint256 c) {
require(b <= a);
c = a - b;
}
function safeMul(uint256 a, uint256 b) public pure returns (uint256 c) {
c = a * b;
require(a == 0 || c / a == b);
}
function safeDiv(uint256 a, uint256 b) public pure returns (uint256 c) {
require(b > 0);
c = a / b;
}
}
/*
* @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 GSN 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.
*/
contract Context is Initializable {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor() internal {}
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/*
* @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 GSN 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.
*/
/**
* @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.
*
* 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.
*/
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* > Note: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = 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 onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
contract StakingV2 is Ownable, ReentrancyGuard {
using Address for address;
using SafeMath for uint256;
using SafeERC20 for IERC20;
// EVENTS
/**
* @dev Emitted when a user deposits tokens.
* @param sender User address.
* @param id User's unique deposit ID.
* @param amount The amount of deposited tokens.
* @param currentBalance Current user balance.
* @param timestamp Operation date
*/
event Deposited(
address indexed sender,
uint256 indexed id,
uint256 amount,
uint256 currentBalance,
uint256 timestamp
);
/**
* @dev Emitted when a user withdraws tokens.
* @param sender User address.
* @param id User's unique deposit ID.
* @param totalWithdrawalAmount The total amount of withdrawn tokens.
* @param currentBalance Balance before withdrawal
* @param timestamp Operation date
*/
event WithdrawnAll(
address indexed sender,
uint256 indexed id,
uint256 totalWithdrawalAmount,
uint256 currentBalance,
uint256 timestamp
);
/**
* @dev Emitted when a user extends lockup.
* @param sender User address.
* @param id User's unique deposit ID.
* @param currentBalance Balance before lockup extension
* @param finalBalance Final balance
* @param timestamp The instant when the lockup is extended.
*/
event ExtendedLockup(
address indexed sender,
uint256 indexed id,
uint256 currentBalance,
uint256 finalBalance,
uint256 timestamp
);
/**
* @dev Emitted when a new Liquidity Provider address value is set.
* @param value A new address value.
* @param sender The owner address at the moment of address changing.
*/
event LiquidityProviderAddressSet(address value, address sender);
struct AddressParam {
address oldValue;
address newValue;
uint256 timestamp;
}
// The deposit user balaces
mapping(address => mapping(uint256 => uint256)) public balances;
// The dates of users deposits/withdraws/extendLockups
mapping(address => mapping(uint256 => uint256)) public depositDates;
// Variable that prevents _deposit method from being called 2 times TODO CHECK
bool private locked;
// Variable to pause all operations
bool private contractPaused = false;
bool private pausedDepositsAndLockupExtensions = false;
// STAKE token
IERC20Mintable public token;
// Reward Token
IERC20Mintable public tokenReward;
// The address for the Liquidity Providers
AddressParam public liquidityProviderAddressParam;
uint256 private constant DAY = 1 days;
uint256 private constant MONTH = 30 days;
uint256 private constant YEAR = 365 days;
// The period after which the new value of the parameter is set
uint256 public constant PARAM_UPDATE_DELAY = 7 days;
// MODIFIERS
/*
* 1 | 2 | 3 | 4 | 5
* 0 Months | 3 Months | 6 Months | 9 Months | 12 Months
*/
modifier validDepositId(uint256 _depositId) {
require(_depositId >= 1 && _depositId <= 5, "Invalid depositId");
_;
}
// Impossible to withdrawAll if you have never deposited.
modifier balanceExists(uint256 _depositId) {
require(balances[msg.sender][_depositId] > 0, "Your deposit is zero");
_;
}
modifier isNotLocked() {
require(locked == false, "Locked, try again later");
_;
}
modifier isNotPaused() {
require(contractPaused == false, "Paused");
_;
}
modifier isNotPausedOperations() {
require(contractPaused == false, "Paused");
_;
}
modifier isNotPausedDepositAndLockupExtensions() {
require(pausedDepositsAndLockupExtensions == false, "Paused Deposits and Extensions");
_;
}
/**
* @dev Pause Deposits, Withdraw, Lockup Extension
*/
function pauseContract(bool value) public onlyOwner {
contractPaused = value;
}
/**
* @dev Pause Deposits and Lockup Extension
*/
function pauseDepositAndLockupExtensions(bool value) public onlyOwner {
pausedDepositsAndLockupExtensions = value;
}
/**
* @dev Initializes the contract. _tokenAddress _tokenReward will have the same address
* @param _owner The owner of the contract.
* @param _tokenAddress The address of the STAKE token contract.
* @param _tokenReward The address of token rewards.
* @param _liquidityProviderAddress The address for the Liquidity Providers reward.
*/
function initializeStaking(
address _owner,
address _tokenAddress,
address _tokenReward,
address _liquidityProviderAddress
) external initializer {
require(_owner != address(0), "Zero address");
require(_tokenAddress.isContract(), "Not a contract address");
Ownable.initialize(msg.sender);
ReentrancyGuard.initialize();
token = IERC20Mintable(_tokenAddress);
tokenReward = IERC20Mintable(_tokenReward);
setLiquidityProviderAddress(_liquidityProviderAddress);
Ownable.transferOwnership(_owner);
}
/**
* @dev Sets the address for the Liquidity Providers reward.
* Can only be called by owner.
* @param _address The new address.
*/
function setLiquidityProviderAddress(address _address) public onlyOwner {
require(_address != address(0), "Zero address");
require(_address != address(this), "Wrong address");
AddressParam memory param = liquidityProviderAddressParam;
if (param.timestamp == 0) {
param.oldValue = _address;
} else if (_paramUpdateDelayElapsed(param.timestamp)) {
param.oldValue = param.newValue;
}
param.newValue = _address;
param.timestamp = _now();
liquidityProviderAddressParam = param;
emit LiquidityProviderAddressSet(_address, msg.sender);
}
/**
* @return Returns true if param update delay elapsed.
*/
function _paramUpdateDelayElapsed(uint256 _paramTimestamp) internal view returns (bool) {
return _now() > _paramTimestamp.add(PARAM_UPDATE_DELAY);
}
/**
* @dev This method is used to deposit tokens to the deposit opened before.
* It calls the internal "_deposit" method and transfers tokens from sender to contract.
* Sender must approve tokens first.
*
* Instead this, user can use the simple "transferFrom" method of OVR token contract to make a deposit.
*
* @param _depositId User's unique deposit ID.
* @param _amount The amount to deposit.
*/
function deposit(uint256 _depositId, uint256 _amount)
public
validDepositId(_depositId)
isNotLocked
isNotPaused
isNotPausedDepositAndLockupExtensions
{
require(_amount > 0, "Amount should be more than 0");
_deposit(msg.sender, _depositId, _amount);
_setLocked(true);
require(token.transferFrom(msg.sender, address(this), _amount), "Transfer failed");
_setLocked(false);
}
/**
* @param _sender The address of the sender.
* @param _depositId User's deposit ID.
* @param _amount The amount to deposit.
*/
function _deposit(
address _sender,
uint256 _depositId,
uint256 _amount
) internal nonReentrant {
uint256 currentBalance = getCurrentBalance(_depositId, _sender);
uint256 finalBalance = calcRewards(_sender, _depositId);
uint256 timestamp = _now();
balances[_sender][_depositId] = _amount.add(finalBalance);
depositDates[_sender][_depositId] = _now();
emit Deposited(_sender, _depositId, _amount, currentBalance, timestamp);
}
/**
* @dev This method is used to withdraw rewards and balance.
* It calls the internal "_withdrawAll" method.
* @param _depositId User's unique deposit ID
*/
function withdrawAll(uint256 _depositId) external balanceExists(_depositId) validDepositId(_depositId) isNotPaused {
require(isLockupPeriodExpired(_depositId), "Too early, Lockup period");
_withdrawAll(msg.sender, _depositId);
}
function _withdrawAll(address _sender, uint256 _depositId)
internal
balanceExists(_depositId)
validDepositId(_depositId)
nonReentrant
{
uint256 currentBalance = getCurrentBalance(_depositId, _sender);
uint256 finalBalance = calcRewards(_sender, _depositId);
require(finalBalance > 0, "Nothing to withdraw");
balances[_sender][_depositId] = 0;
_setLocked(true);
require(tokenReward.transfer(_sender, finalBalance), "Liquidity pool transfer failed");
_setLocked(false);
emit WithdrawnAll(_sender, _depositId, finalBalance, currentBalance, _now());
}
/**
* This method is used to extend lockup. It is available if your lockup period is expired and if depositId != 1
* It calls the internal "_extendLockup" method.
* @param _depositId User's unique deposit ID
*/
function extendLockup(uint256 _depositId)
external
balanceExists(_depositId)
validDepositId(_depositId)
isNotPaused
isNotPausedDepositAndLockupExtensions
{
require(_depositId != 1, "No lockup is set up");
_extendLockup(msg.sender, _depositId);
}
function _extendLockup(address _sender, uint256 _depositId) internal nonReentrant {
uint256 timestamp = _now();
uint256 currentBalance = getCurrentBalance(_depositId, _sender);
uint256 finalBalance = calcRewards(_sender, _depositId);
balances[_sender][_depositId] = finalBalance;
depositDates[_sender][_depositId] = timestamp;
emit ExtendedLockup(_sender, _depositId, currentBalance, finalBalance, timestamp);
}
function isLockupPeriodExpired(uint256 _depositId) public view validDepositId(_depositId) returns (bool) {
uint256 lockPeriod;
if (_depositId == 1) {
lockPeriod = 0;
} else if (_depositId == 2) {
lockPeriod = MONTH * 3; // 3 months
} else if (_depositId == 3) {
lockPeriod = MONTH * 6; // 6 months
} else if (_depositId == 4) {
lockPeriod = MONTH * 9; // 9 months
} else if (_depositId == 5) {
lockPeriod = MONTH * 12; // 12 months
}
if (_now() > depositDates[msg.sender][_depositId].add(lockPeriod)) {
return true;
} else {
return false;
}
}
function pow(int128 _x, uint256 _n) public pure returns (int128 r) {
r = ABDKMath64x64.fromUInt(1);
while (_n > 0) {
if (_n % 2 == 1) {
r = ABDKMath64x64.mul(r, _x);
_n -= 1;
} else {
_x = ABDKMath64x64.mul(_x, _x);
_n /= 2;
}
}
}
/**
* This method is calcuate final compouded capital.
* @param _principal User's balance
* @param _ratio Interest rate
* @param _n Periods is timestamp
* @return finalBalance The final compounded capital
*
* A = C ( 1 + rate )^t
*/
function compound(
uint256 _principal,
uint256 _ratio,
uint256 _n
) public view returns (uint256) {
uint256 daysCount = _n.div(DAY);
return
ABDKMath64x64.mulu(
pow(ABDKMath64x64.add(ABDKMath64x64.fromUInt(1), ABDKMath64x64.divu(_ratio, 10**18)), daysCount),
_principal
);
}
/**
* This moethod is used to calculate final compounded balance and is based on deposit duration and deposit id.
* Each deposit mode is characterized by the lockup period and interest rate.
* At the expiration of the lockup period the final compounded capital
* will use minimum interest rate.
*
* This function can be called at any time to get the current total reward.
* @param _sender Sender Address.
* @param _depositId The depositId
* @return finalBalance The final compounded capital
*/
function calcRewards(address _sender, uint256 _depositId) public view validDepositId(_depositId) returns (uint256) {
uint256 timePassed = _now().sub(depositDates[_sender][_depositId]);
uint256 currentBalance = getCurrentBalance(_depositId, _sender);
uint256 finalBalance;
uint256 ratio;
uint256 lockPeriod;
if (_depositId == 1) {
ratio = 100000000000000; // APY 3.7% InterestRate = 0.01
lockPeriod = 0;
} else if (_depositId == 2) {
ratio = 300000000000000; // APY 11.6% InterestRate = 0.03
lockPeriod = MONTH * 3; // 3 months
} else if (_depositId == 3) {
ratio = 400000000000000; // APY 15.7% InterestRate = 0.04
lockPeriod = MONTH * 6; // 6 months
} else if (_depositId == 4) {
ratio = 600000000000000; // APY 25.5% InterestRate = 0.06
lockPeriod = MONTH * 9; // 9 months
} else if (_depositId == 5) {
ratio = 800000000000000; // APY 33.9% InterestRate = 0.08
lockPeriod = YEAR; // 12 months
}
// You can't have earnings without balance
if (currentBalance == 0) {
return finalBalance = 0;
}
// No lockup
if (_depositId == 1) {
finalBalance = compound(currentBalance, ratio, timePassed);
return finalBalance;
}
// If you have an uncovered period from lockup, you still get rewards at the minimum rate
if (timePassed > lockPeriod) {
uint256 rewardsWithLockup = compound(currentBalance, ratio, lockPeriod).sub(currentBalance);
finalBalance = compound(rewardsWithLockup.add(currentBalance), 100000000000000, timePassed.sub(lockPeriod));
return finalBalance;
}
finalBalance = compound(currentBalance, ratio, timePassed);
return finalBalance;
}
function getCurrentBalance(uint256 _depositId, address _address) public view returns (uint256 addressBalance) {
addressBalance = balances[_address][_depositId];
}
/**
* @return Returns current liquidity providers reward address.
*/
function liquidityProviderAddress() public view returns (address) {
AddressParam memory param = liquidityProviderAddressParam;
return param.newValue;
}
/**
* @dev Sets lock to prevent reentrance.
*/
function _setLocked(bool _locked) internal {
locked = _locked;
}
function senderCurrentBalance() public view returns (uint256) {
return msg.sender.balance;
}
/**
* @return Returns current timestamp.
*/
function _now() internal view returns (uint256) {
// Note that the timestamp can have a 900-second error:
// https://github.com/ethereum/wiki/blob/c02254611f218f43cbb07517ca8e5d00fd6d6d75/Block-Protocol-2.0.md
// return now; // solium-disable-line security/no-block-members
return block.timestamp;
}
}
{
"compilationTarget": {
"StakingV2.sol": "StakingV2"
},
"evmVersion": "istanbul",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"finalBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ExtendedLockup","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"value","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"LiquidityProviderAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalWithdrawalAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WithdrawnAll","type":"event"},{"constant":true,"inputs":[],"name":"PARAM_UPDATE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_depositId","type":"uint256"}],"name":"calcRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_principal","type":"uint256"},{"internalType":"uint256","name":"_ratio","type":"uint256"},{"internalType":"uint256","name":"_n","type":"uint256"}],"name":"compound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_depositId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"depositDates","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_depositId","type":"uint256"}],"name":"extendLockup","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_depositId","type":"uint256"},{"internalType":"address","name":"_address","type":"address"}],"name":"getCurrentBalance","outputs":[{"internalType":"uint256","name":"addressBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_tokenReward","type":"address"},{"internalType":"address","name":"_liquidityProviderAddress","type":"address"}],"name":"initializeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_depositId","type":"uint256"}],"name":"isLockupPeriodExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"liquidityProviderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"liquidityProviderAddressParam","outputs":[{"internalType":"address","name":"oldValue","type":"address"},{"internalType":"address","name":"newValue","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"pauseContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"pauseDepositAndLockupExtensions","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"int128","name":"_x","type":"int128"},{"internalType":"uint256","name":"_n","type":"uint256"}],"name":"pow","outputs":[{"internalType":"int128","name":"r","type":"int128"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"senderCurrentBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setLiquidityProviderAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20Mintable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenReward","outputs":[{"internalType":"contract IERC20Mintable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_depositId","type":"uint256"}],"name":"withdrawAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]