Overview
ETH Balance
ETH Value
$0.00Latest 13 from a total of 13 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Create Pair | 110367470 | 923 days ago | IN | 0 ETH | 0.000087851299 | ||||
| Create Pair | 109742308 | 937 days ago | IN | 0 ETH | 0.000128150605 | ||||
| Create Pair | 109349510 | 946 days ago | IN | 0 ETH | 0.000030089902 | ||||
| Create Pair | 109146632 | 951 days ago | IN | 0 ETH | 0.000040304055 | ||||
| Create Pair | 109140234 | 951 days ago | IN | 0 ETH | 0.000041045896 | ||||
| Create Pair | 109138745 | 951 days ago | IN | 0 ETH | 0.000047186314 | ||||
| Create Pair | 109090191 | 952 days ago | IN | 0 ETH | 0.000031983839 | ||||
| Create Pair | 109041837 | 953 days ago | IN | 0 ETH | 0.000036975018 | ||||
| Create Pair | 109041610 | 953 days ago | IN | 0 ETH | 0.000034106896 | ||||
| Create Pair | 108954349 | 955 days ago | IN | 0 ETH | 0.000124201948 | ||||
| Create Pair | 108954115 | 955 days ago | IN | 0 ETH | 0.000104978339 | ||||
| Create Pair | 108927585 | 956 days ago | IN | 0 ETH | 0.005545337636 | ||||
| Create Pair | 108927585 | 956 days ago | IN | 0 ETH | 0.00559517992 |
Latest 13 internal transactions
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 110367470 | 923 days ago | Contract Creation | 0 ETH | |||
| 109742308 | 937 days ago | Contract Creation | 0 ETH | |||
| 109349510 | 946 days ago | Contract Creation | 0 ETH | |||
| 109146632 | 951 days ago | Contract Creation | 0 ETH | |||
| 109140234 | 951 days ago | Contract Creation | 0 ETH | |||
| 109138745 | 951 days ago | Contract Creation | 0 ETH | |||
| 109090191 | 952 days ago | Contract Creation | 0 ETH | |||
| 109041837 | 953 days ago | Contract Creation | 0 ETH | |||
| 109041610 | 953 days ago | Contract Creation | 0 ETH | |||
| 108954349 | 955 days ago | Contract Creation | 0 ETH | |||
| 108954115 | 955 days ago | Contract Creation | 0 ETH | |||
| 108927585 | 956 days ago | Contract Creation | 0 ETH | |||
| 108927585 | 956 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;
import { ILiquidationSource, LiquidationPair, SD59x18 } from "./LiquidationPair.sol";
/// @title LiquidationPairFactory
/// @author G9 Software Inc.
/// @notice Factory contract for deploying LiquidationPair contracts.
contract LiquidationPairFactory {
/* ============ Events ============ */
/// @notice Emitted when a new LiquidationPair is created
/// @param pair The address of the new pair
/// @param tokenIn The input token for the pair
/// @param tokenOut The output token for the pair
/// @param source The liquidation source that the pair is using
/// @param periodLength The duration of auctions
/// @param firstPeriodStartsAt The start time offset of auctions
/// @param targetFirstSaleTime The target time for the first auction
/// @param decayConstant The decay constant that the pair is using
/// @param initialAmountIn The initial amount of input tokens (used to compute initial exchange rate)
/// @param initialAmountOut The initial amount of output tokens (used to compute initial exchange rate)
/// @param minimumAuctionAmount The minimum auction size in output tokens
event PairCreated(
LiquidationPair indexed pair,
address indexed tokenIn,
address indexed tokenOut,
ILiquidationSource source,
uint32 periodLength,
uint32 firstPeriodStartsAt,
uint32 targetFirstSaleTime,
SD59x18 decayConstant,
uint104 initialAmountIn,
uint104 initialAmountOut,
uint256 minimumAuctionAmount
);
/* ============ Variables ============ */
/// @notice Tracks an array of all pairs created by this factory
LiquidationPair[] public allPairs;
/* ============ Mappings ============ */
/**
* @notice Mapping to verify if a LiquidationPair has been deployed via this factory.
* @dev LiquidationPair address => boolean
*/
mapping(LiquidationPair => bool) public deployedPairs;
/// @notice Creates a new LiquidationPair and registers it within the factory
/// @param _source The liquidation source that the pair will use
/// @param _tokenIn The input token for the pair
/// @param _tokenOut The output token for the pair
/// @param _periodLength The duration of auctions
/// @param _firstPeriodStartsAt The start time offset of auctions
/// @param _targetFirstSaleTime The target time for the first auction
/// @param _decayConstant The decay constant that the pair will use. This determines how rapidly the price changes.
/// @param _initialAmountIn The initial amount of input tokens (used to compute initial exchange rate)
/// @param _initialAmountOut The initial amount of output tokens (used to compute initial exchange rate)
/// @param _minimumAuctionAmount The minimum auction size in output tokens
/// @return The address of the new pair
function createPair(
ILiquidationSource _source,
address _tokenIn,
address _tokenOut,
uint32 _periodLength,
uint32 _firstPeriodStartsAt,
uint32 _targetFirstSaleTime,
SD59x18 _decayConstant,
uint104 _initialAmountIn,
uint104 _initialAmountOut,
uint256 _minimumAuctionAmount
) external returns (LiquidationPair) {
LiquidationPair _liquidationPair = new LiquidationPair(
_source,
_tokenIn,
_tokenOut,
_periodLength,
_firstPeriodStartsAt,
_targetFirstSaleTime,
_decayConstant,
_initialAmountIn,
_initialAmountOut,
_minimumAuctionAmount
);
allPairs.push(_liquidationPair);
deployedPairs[_liquidationPair] = true;
emit PairCreated(
_liquidationPair,
_tokenIn,
_tokenOut,
_source,
_periodLength,
_firstPeriodStartsAt,
_targetFirstSaleTime,
_decayConstant,
_initialAmountIn,
_initialAmountOut,
_minimumAuctionAmount
);
return _liquidationPair;
}
/**
* @notice Total number of LiquidationPair deployed by this factory.
* @return Number of LiquidationPair deployed by this factory.
*/
function totalPairs() external view returns (uint256) {
return allPairs.length;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;
import { SafeCast } from "openzeppelin/utils/math/SafeCast.sol";
import { ILiquidationSource } from "pt-v5-liquidator-interfaces/ILiquidationSource.sol";
import { IFlashSwapCallback } from "pt-v5-liquidator-interfaces/IFlashSwapCallback.sol";
import { ILiquidationPair } from "pt-v5-liquidator-interfaces/ILiquidationPair.sol";
import { SD59x18, uEXP_MAX_INPUT, wrap, convert, unwrap } from "prb-math/SD59x18.sol";
import { ContinuousGDA } from "./libraries/ContinuousGDA.sol";
/// @notice Thrown when constructed with a zero initial amount in
error AmountInZero();
/// @notice Thrown when constructed with a zero initial amount out
error AmountOutZero();
/// @notice Thrown when the target sale time is greater than or equal to the period length
/// @param passedTargetSaleTime The requested target sale time
/// @param periodLength The period length
error TargetFirstSaleTimeGePeriodLength(uint256 passedTargetSaleTime, uint256 periodLength);
/// @notice Thrown when the swap exceeds the available amount
/// @param amountOut The requested amount
/// @param available The available amount
error SwapExceedsAvailable(uint256 amountOut, uint256 available);
/// @notice Thrown when the actual swap amount in exceeds the user defined maximum amount in
/// @param amountInMax The user-defined max amount in
/// @param amountIn The actual amount in
error SwapExceedsMax(uint256 amountInMax, uint256 amountIn);
/// @notice Thrown when the decay constant is too large
/// @param maxDecayConstant The maximum decay constant
/// @param decayConstant The requested decay constant
error DecayConstantTooLarge(SD59x18 maxDecayConstant, SD59x18 decayConstant);
/// @notice Throw when the amount in for a swap is zero
/// @param amountOut The amount out
error PurchasePriceIsZero(uint256 amountOut);
/// @notice Thrown when the liquidation source is the zero address
error LiquidationSourceZeroAddress();
/// @notice Thrown when the token in is the zero address
error TokenInZeroAddress();
/// @notice Thrown when the token out is the zero address
error TokenOutZeroAddress();
error EmissionRateIsZero();
/// @notice Thrown when the receiver of the swap is the zero address
error ReceiverIsZero();
uint256 constant UINT192_MAX = type(uint192).max;
/***
* @title LiquidationPair
* @author G9 Software Inc.
* @notice Auctions one token for another in a periodic continuous gradual dutch auction. Auctions occur over a limit period so that the price can be adjusted.
* @dev This contract is designed to be used with the LiquidationRouter contract.
*/
contract LiquidationPair is ILiquidationPair {
/* ============ Events ============ */
/// @notice Emitted when a new auction is started
/// @param lastNonZeroAmountIn The total tokens in for the previous non-zero auction
/// @param lastNonZeroAmountOut The total tokens out for the previous non-zero auction
/// @param lastAuctionTime The timestamp at which the auction starts
/// @param period The current auction period
/// @param emissionRate The rate of token emissions for the current auction
/// @param initialPrice The initial price for the current auction
event StartedAuction(
uint104 lastNonZeroAmountIn,
uint104 lastNonZeroAmountOut,
uint48 lastAuctionTime,
uint48 indexed period,
SD59x18 emissionRate,
SD59x18 initialPrice
);
/// @notice Emitted when a swap is made
/// @param sender The sender of the swap
/// @param receiver The receiver of the swap
/// @param amountOut The amount of tokens out
/// @param amountInMax The maximum amount of tokens in
/// @param amountIn The actual amount of tokens in
event SwappedExactAmountOut(
address indexed sender,
address indexed receiver,
uint256 amountOut,
uint256 amountInMax,
uint256 amountIn,
bytes flashSwapData
);
/* ============ Variables ============ */
/// @notice The liquidation source that the pair is using. The source executes the actual token swap, while the pair handles the pricing.
ILiquidationSource public immutable source;
/// @notice The token that is used to pay for auctions
address public immutable tokenIn;
/// @notice The token that is being auctioned.
address public immutable tokenOut;
/// @notice The rate at which the price decays
SD59x18 public immutable decayConstant;
/// @notice The duration of each auction.
uint256 public immutable periodLength;
/// @notice Sets the beginning timestamp for the first period.
/// @dev If the firstPeriodStartsAt timestamp is in the future, the auctions won't run until then.
uint256 public immutable firstPeriodStartsAt;
/// @notice The time within an auction at which the price of available tokens matches the previous non-zero exchange rate.
uint32 public immutable targetFirstSaleTime;
/// @notice Require a minimum number of tokens before an auction is triggered.
/// @dev This is important, because the gas cost ultimately determines the efficiency of the swap.
/// If gas cost to auction is 10 cents and the auction is for 11 cents, then the auction price will be driven to zero to make up for the difference.
/// If gas cost is 10 cents and we're seeking an efficiency of at least 90%, then the minimum auction amount should be $1 worth of tokens.
uint256 public immutable minimumAuctionAmount;
/// @notice The last non-zero total tokens in for an auction. This is used to configure the target price for the next auction.
uint104 internal _lastNonZeroAmountIn;
/// @notice The last non-zero total tokens out for an auction. This is used to configure the target price for the next auction.
uint104 internal _lastNonZeroAmountOut;
/// @notice The current auction period. Note that this number can wrap.
uint48 internal _period;
/// @notice The total tokens in for the current auction.
uint104 internal _amountInForPeriod;
/// @notice The total tokens out for the current auction.
uint104 internal _amountOutForPeriod;
/// @notice The timestamp at which emissions have been consumed to for the current auction
uint48 internal _lastAuctionTime;
/// @notice The rate of token emissions for the current auction
SD59x18 internal _emissionRate;
/// @notice The initial price for the current auction
SD59x18 internal _initialPrice;
/* ============ Constructor ============ */
/// @notice Construct a new pair
/// @param _source The liquidation source to use for the pair
/// @param _tokenIn The token that is used to pay for auctions
/// @param _tokenOut The token that is being auctioned
/// @param _periodLength The duration of each auction.
/// @param _firstPeriodStartsAt Sets the beginning timestamp for the first period
/// @param _targetFirstSaleTime The time within an auction at which the price of available tokens matches the previous non-zero exchange rate
/// @param _decayConstant The rate at which the price decays
/// @param _initialAmountIn The initial amount of tokens in for the first auction (used for the initial exchange rate)
/// @param _initialAmountOut The initial amount of tokens out for the first auction (used for the initial exchange rate)
/// @param _minimumAuctionAmount Require a minimum number of tokens before an auction is triggered.
constructor(
ILiquidationSource _source,
address _tokenIn,
address _tokenOut,
uint32 _periodLength,
uint32 _firstPeriodStartsAt,
uint32 _targetFirstSaleTime,
SD59x18 _decayConstant,
uint104 _initialAmountIn,
uint104 _initialAmountOut,
uint256 _minimumAuctionAmount
) {
if (address(0) == address(_source)) revert LiquidationSourceZeroAddress();
if (address(0) == address(_tokenIn)) revert TokenInZeroAddress();
if (address(0) == address(_tokenOut)) revert TokenOutZeroAddress();
source = _source;
tokenIn = _tokenIn;
tokenOut = _tokenOut;
decayConstant = _decayConstant;
periodLength = _periodLength;
firstPeriodStartsAt = _firstPeriodStartsAt;
targetFirstSaleTime = _targetFirstSaleTime;
SD59x18 period59 = convert(SafeCast.toInt256(uint256(_periodLength)));
if (_decayConstant.mul(period59).unwrap() > uEXP_MAX_INPUT) {
revert DecayConstantTooLarge(wrap(uEXP_MAX_INPUT).div(period59), _decayConstant);
}
if (targetFirstSaleTime >= periodLength) {
revert TargetFirstSaleTimeGePeriodLength(targetFirstSaleTime, periodLength);
}
if (_initialAmountIn == 0) {
revert AmountInZero();
}
if (_initialAmountOut == 0) {
revert AmountOutZero();
}
_lastNonZeroAmountIn = _initialAmountIn;
_lastNonZeroAmountOut = _initialAmountOut;
minimumAuctionAmount = _minimumAuctionAmount;
_updateAuction(0);
}
/* ============ External Read Methods ============ */
/// @inheritdoc ILiquidationPair
function target() external returns (address) {
return source.targetOf(tokenIn);
}
/// @inheritdoc ILiquidationPair
function maxAmountOut() external returns (uint256) {
_checkUpdateAuction();
return _maxAmountOut();
}
/// @notice Returns the maximum amount of tokens in
/// @return The max number of tokens in
function maxAmountIn() external returns (uint256) {
_checkUpdateAuction();
SD59x18 eRate = _emissionRate;
if (eRate.unwrap() == 0) {
return 0;
}
return _computeExactAmountIn(_maxAmountOut(), eRate);
}
/// @inheritdoc ILiquidationPair
function computeExactAmountIn(uint256 _amountOut) external returns (uint256) {
_checkUpdateAuction();
SD59x18 eRate = _emissionRate;
if (eRate.unwrap() == 0) {
revert EmissionRateIsZero();
}
return _computeExactAmountIn(_amountOut, eRate);
}
/// @notice Returns the total input tokens for the current auction.
/// @return Total tokens in
function amountInForPeriod() external returns (uint104) {
_checkUpdateAuction();
return _amountInForPeriod;
}
/// @notice Returns the total output tokens for the current auction.
/// @return Total tokens out
function amountOutForPeriod() external returns (uint104) {
_checkUpdateAuction();
return _amountOutForPeriod;
}
/// @notice Returns the timestamp to which emissions have been consumed.
/// @return The timestamp to which emissions have been consumed.
function lastAuctionTime() external returns (uint48) {
_checkUpdateAuction();
return _lastAuctionTime;
}
/// @notice Returns the emission rate in tokens per second for current auction
/// @return The emission rate
function emissionRate() external returns (SD59x18) {
_checkUpdateAuction();
return _emissionRate;
}
/// @notice Returns the initial price for the current auction
/// @return The initial price
function initialPrice() external returns (SD59x18) {
_checkUpdateAuction();
return _initialPrice;
}
/// @inheritdoc ILiquidationPair
function swapExactAmountOut(
address _receiver,
uint256 _amountOut,
uint256 _amountInMax,
bytes memory _flashSwapData
) external returns (uint256) {
if (_receiver == address(0)) {
revert ReceiverIsZero();
}
_checkUpdateAuction();
SD59x18 eRate = _emissionRate;
if (eRate.unwrap() == 0) {
revert EmissionRateIsZero();
}
uint256 swapAmountIn = _computeExactAmountIn(_amountOut, eRate);
if (swapAmountIn == 0) {
revert PurchasePriceIsZero(_amountOut);
}
if (swapAmountIn > _amountInMax) {
revert SwapExceedsMax(_amountInMax, swapAmountIn);
}
_amountInForPeriod = _amountInForPeriod + SafeCast.toUint104(swapAmountIn);
_amountOutForPeriod = _amountOutForPeriod + SafeCast.toUint104(_amountOut);
_lastAuctionTime =
_lastAuctionTime +
SafeCast.toUint48(SafeCast.toUint256(convert(convert(SafeCast.toInt256(_amountOut)).div(eRate))));
bytes memory transferTokensOutData = source.transferTokensOut(
msg.sender,
_receiver,
tokenOut,
_amountOut
);
if (_flashSwapData.length > 0) {
IFlashSwapCallback(_receiver).flashSwapCallback(
msg.sender,
swapAmountIn,
_amountOut,
_flashSwapData
);
}
source.verifyTokensIn(
tokenIn,
swapAmountIn,
transferTokensOutData
);
emit SwappedExactAmountOut(msg.sender, _receiver, _amountOut, _amountInMax, swapAmountIn, _flashSwapData);
return swapAmountIn;
}
/// @notice Computes the elapsed time within the auction
function getElapsedTime() external returns (uint256) {
_checkUpdateAuction();
return uint256(convert(_getElapsedTime()));
}
/// @notice Returns the current auction start time
/// @return The start timestamp
function getPeriodStart() external returns (uint256) {
_checkUpdateAuction();
return _getPeriodStart(_computePeriod());
}
/// @notice Returns the current auction end time
/// @return The end timestamp
function getPeriodEnd() external returns (uint256) {
_checkUpdateAuction();
return _getPeriodStart(_computePeriod()) + periodLength;
}
/// @notice Returns the last non-zero auction total input tokens
/// @return Total input tokens
function lastNonZeroAmountIn() external returns (uint112) {
_checkUpdateAuction();
return _lastNonZeroAmountIn;
}
/// @notice Returns the last non-zero auction total output tokens
/// @return Total output tokens
function lastNonZeroAmountOut() external returns (uint112) {
_checkUpdateAuction();
return _lastNonZeroAmountOut;
}
/* ============ Internal Functions ============ */
/// @notice Computes the maximum amount of output tokens that can be purchased
/// @return Maximum amount of output tokens
function _maxAmountOut() internal returns (uint256) {
uint256 emissions = SafeCast.toUint256(convert(_emissionRate.mul(_getElapsedTime())));
uint256 liquidatable = source.liquidatableBalanceOf(tokenOut);
return emissions > liquidatable ? liquidatable : emissions;
}
/// @notice Computes the elapsed time within the current auction
/// @return The elapsed time
function _getElapsedTime() internal view returns (SD59x18) {
uint48 cachedLastAuctionTime = _lastAuctionTime;
if (block.timestamp < cachedLastAuctionTime) {
return wrap(0);
}
return (
convert(SafeCast.toInt256(block.timestamp)).sub(convert(SafeCast.toInt256(cachedLastAuctionTime)))
);
}
/// @notice Computes the exact amount of input tokens required to purchase the given amount of output tokens
/// @param _amountOut The number of output tokens desired
/// @return The number of input tokens needed
function _computeExactAmountIn(uint256 _amountOut, SD59x18 emissionRate_) internal returns (uint256) {
if (_amountOut == 0) {
return 0;
}
uint256 maxOut = _maxAmountOut();
if (_amountOut > maxOut) {
revert SwapExceedsAvailable(_amountOut, maxOut);
}
SD59x18 elapsed = _getElapsedTime();
uint256 purchasePrice = SafeCast.toUint256(convert(ContinuousGDA.purchasePrice(
convert(SafeCast.toInt256(_amountOut)),
emissionRate_,
_initialPrice,
decayConstant,
elapsed
).ceil()));
return purchasePrice;
}
/// @notice Checks to see if a new auction has started, and updates the state if so
function _checkUpdateAuction() internal {
uint256 currentPeriod = _computePeriod();
if (currentPeriod != _period) {
_updateAuction(currentPeriod);
}
}
/// @notice Updates the current auction to the given period
/// @param __period The period that the auction should be updated to
function _updateAuction(uint256 __period) internal {
if (block.timestamp < firstPeriodStartsAt) {
return;
}
uint104 cachedLastNonZeroAmountIn;
uint104 cachedLastNonZeroAmountOut;
if (_amountInForPeriod > 0 && _amountOutForPeriod > 0) {
// if we sold something, then update the previous non-zero amount
_lastNonZeroAmountIn = _amountInForPeriod;
_lastNonZeroAmountOut = _amountOutForPeriod;
cachedLastNonZeroAmountIn = _amountInForPeriod;
cachedLastNonZeroAmountOut = _amountOutForPeriod;
} else {
cachedLastNonZeroAmountIn = _lastNonZeroAmountIn;
cachedLastNonZeroAmountOut = _lastNonZeroAmountOut;
}
_period = uint48(__period);
delete _amountInForPeriod;
delete _amountOutForPeriod;
_lastAuctionTime = SafeCast.toUint48(firstPeriodStartsAt + periodLength * __period);
uint256 auctionAmount = source.liquidatableBalanceOf(tokenOut);
if (auctionAmount < minimumAuctionAmount) {
// do not release funds if the minimum is not met
auctionAmount = 0;
} else if (auctionAmount > UINT192_MAX) {
auctionAmount = UINT192_MAX;
}
SD59x18 emissionRate_ = convert(SafeCast.toInt256(auctionAmount)).div(convert(SafeCast.toInt32(SafeCast.toInt256(periodLength))));
_emissionRate = emissionRate_;
if (emissionRate_.unwrap() != 0) {
// compute k
SD59x18 timeSinceLastAuctionStart = convert(SafeCast.toInt256(uint256(targetFirstSaleTime)));
SD59x18 purchaseAmount = timeSinceLastAuctionStart.mul(emissionRate_);
SD59x18 exchangeRateAmountInToAmountOut =
convert(SafeCast.toInt256(uint256(cachedLastNonZeroAmountIn))).div(
convert(SafeCast.toInt256(uint256(cachedLastNonZeroAmountOut)))
);
SD59x18 price = exchangeRateAmountInToAmountOut.mul(purchaseAmount);
_initialPrice = ContinuousGDA.computeK(
emissionRate_,
decayConstant,
timeSinceLastAuctionStart,
purchaseAmount,
price
);
} else {
_initialPrice = wrap(0);
}
emit StartedAuction(
cachedLastNonZeroAmountIn,
cachedLastNonZeroAmountOut,
_lastAuctionTime,
uint48(__period),
emissionRate_,
_initialPrice
);
}
/// @notice Computes the start time of the given auction period
/// @param __period The auction period, in terms of number of periods since firstPeriodStartsAt
/// @return The start timestamp of the given period
function _getPeriodStart(uint256 __period) internal view returns (uint256) {
return firstPeriodStartsAt + __period * periodLength;
}
/// @notice Computes the current auction period
/// @return the current period
function _computePeriod() internal view returns (uint256) {
if (block.timestamp < firstPeriodStartsAt) {
return 0;
}
return (block.timestamp - firstPeriodStartsAt) / periodLength;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such 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.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ILiquidationSource {
/**
* @notice Get the available amount of tokens that can be swapped.
* @param tokenOut Address of the token to get available balance for
* @return uint256 Available amount of `token`
*/
function liquidatableBalanceOf(address tokenOut) external returns (uint256);
/**
* @notice Transfers tokens to the receiver
* @param sender Address that triggered the liquidation
* @param receiver Address of the account that will receive `tokenOut`
* @param tokenOut Address of the token being bought
* @param amountOut Amount of token being bought
*/
function transferTokensOut(
address sender,
address receiver,
address tokenOut,
uint256 amountOut
) external returns (bytes memory);
/**
* @notice Verifies that tokens have been transferred in.
* @param tokenIn Address of the token being sold
* @param amountIn Amount of token being sold
* @param transferTokensOutData Data returned by the corresponding transferTokensOut call
*/
function verifyTokensIn(
address tokenIn,
uint256 amountIn,
bytes calldata transferTokensOutData
) external;
/**
* @notice Get the address that will receive `tokenIn`.
* @param tokenIn Address of the token to get the target address for
* @return address Address of the target
*/
function targetOf(address tokenIn) external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Interface for the flash swap callback
interface IFlashSwapCallback {
/// @notice Called on the token receiver by the LiquidationPair during a liquidation if the flashSwap data length is non-zero
/// @param _sender The address that triggered the liquidation swap
/// @param _amountOut The amount of tokens that were sent to the receiver
/// @param _amountIn The amount of tokens expected to be sent to the target
/// @param _flashSwapData The flash swap data that was passed into the swap function.
function flashSwapCallback(
address _sender,
uint256 _amountIn,
uint256 _amountOut,
bytes calldata _flashSwapData
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ILiquidationPair {
/**
* @notice Get the address that will receive `tokenIn`.
* @return Address of the target
*/
function target() external returns (address);
/**
* @notice Gets the maximum amount of tokens that can be swapped out from the source.
* @return The maximum amount of tokens that can be swapped out.
*/
function maxAmountOut() external returns (uint256);
/**
* @notice Swaps the given amount of tokens out and ensures the amount of tokens in doesn't exceed the given maximum.
* @dev The amount of tokens being swapped in must be sent to the target before calling this function.
* @param _receiver The address to send the tokens to.
* @param _amountOut The amount of tokens to receive out.
* @param _amountInMax The maximum amount of tokens to send in.
* @param _flashSwapData If non-zero, the _receiver is called with this data prior to
* @return The amount of tokens sent in.
*/
function swapExactAmountOut(
address _receiver,
uint256 _amountOut,
uint256 _amountInMax,
bytes calldata _flashSwapData
) external returns (uint256);
/**
* @notice Computes the exact amount of tokens to send in for the given amount of tokens to receive out.
* @param _amountOut The amount of tokens to receive out.
* @return The amount of tokens to send in.
*/
function computeExactAmountIn(uint256 _amountOut) external returns (uint256);
}// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; /* ██████╗ ██████╗ ██████╗ ███╗ ███╗ █████╗ ████████╗██╗ ██╗ ██╔══██╗██╔══██╗██╔══██╗████╗ ████║██╔══██╗╚══██╔══╝██║ ██║ ██████╔╝██████╔╝██████╔╝██╔████╔██║███████║ ██║ ███████║ ██╔═══╝ ██╔══██╗██╔══██╗██║╚██╔╝██║██╔══██║ ██║ ██╔══██║ ██║ ██║ ██║██████╔╝██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ███████╗██████╗ ███████╗ █████╗ ██╗ ██╗ ██╗ █████╗ ██╔════╝██╔══██╗██╔════╝██╔══██╗╚██╗██╔╝███║██╔══██╗ ███████╗██║ ██║███████╗╚██████║ ╚███╔╝ ╚██║╚█████╔╝ ╚════██║██║ ██║╚════██║ ╚═══██║ ██╔██╗ ██║██╔══██╗ ███████║██████╔╝███████║ █████╔╝██╔╝ ██╗ ██║╚█████╔╝ ╚══════╝╚═════╝ ╚══════╝ ╚════╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ */ import "./sd59x18/Casting.sol"; import "./sd59x18/Constants.sol"; import "./sd59x18/Conversions.sol"; import "./sd59x18/Errors.sol"; import "./sd59x18/Helpers.sol"; import "./sd59x18/Math.sol"; import "./sd59x18/ValueType.sol";
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;
import { SD59x18, convert, unwrap } from "prb-math/SD59x18.sol";
import { SafeSD59x18 } from "./SafeSD59x18.sol";
/// @title ContinuousGDA
/// @author G9 Software Inc.
/// @notice Implements the Continous Gradual Dutch Auction formula
/// See https://www.paradigm.xyz/2022/04/gda
/// @dev Pricing formula adapted from https://github.com/FrankieIsLost/gradual-dutch-auction/blob/master/src/ContinuousGDA.sol
library ContinuousGDA {
using SafeSD59x18 for SD59x18;
/// @notice a helpful constant
SD59x18 internal constant ONE = SD59x18.wrap(1e18);
/// @notice Calculate purchase price for a given amount of tokens
/// @param _amount The amount of tokens to purchase
/// @param _emissionRate The emission rate of the CGDA
/// @param _k The initial price of the CGDA
/// @param _decayConstant The decay constant of the CGDA
/// @param _timeSinceLastAuctionStart The elapsed time since the last consumed timestamp
/// @return The purchase price for the given amount of tokens
function purchasePrice(
SD59x18 _amount,
SD59x18 _emissionRate,
SD59x18 _k,
SD59x18 _decayConstant,
SD59x18 _timeSinceLastAuctionStart
) internal pure returns (SD59x18) {
if (_amount.unwrap() == 0) {
return SD59x18.wrap(0);
}
SD59x18 topE = _decayConstant.mul(_amount).div(_emissionRate);
topE = topE.safeExp().sub(ONE);
SD59x18 bottomE = _decayConstant.mul(_timeSinceLastAuctionStart);
bottomE = bottomE.safeExp();
SD59x18 result;
result = _k.div(bottomE).mul(topE.div(_decayConstant));
return result;
}
/// @notice Computes an initial price for the CGDA such that the purchase amount will cost the price at the given timestamp
/// @param _emissionRate The emission rate of the CGDA
/// @param _decayConstant The decay constant of the CGDA
/// @param _targetFirstSaleTime The timestamp at which the CGDA price for the given amount matches the given price
/// @param _purchaseAmount The amount of tokens to purchase
/// @param _price The price to be paid for the amount of tokens
function computeK(
SD59x18 _emissionRate,
SD59x18 _decayConstant,
SD59x18 _targetFirstSaleTime,
SD59x18 _purchaseAmount,
SD59x18 _price
) internal pure returns (SD59x18) {
SD59x18 topE = _decayConstant.mul(_targetFirstSaleTime).safeExp();
SD59x18 denominator = (_decayConstant.mul(_purchaseAmount).div(_emissionRate)).safeExp().sub(ONE);
SD59x18 result = topE.div(denominator);
SD59x18 multiplier = _decayConstant.mul(_price);
return result.mul(multiplier);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./Errors.sol" as CastingErrors;
import { MAX_UINT128, MAX_UINT40 } from "../Common.sol";
import { uMAX_SD1x18, uMIN_SD1x18 } from "../sd1x18/Constants.sol";
import { SD1x18 } from "../sd1x18/ValueType.sol";
import { uMAX_UD2x18 } from "../ud2x18/Constants.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "../ud60x18/ValueType.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Casts an SD59x18 number into int256.
/// @dev This is basically a functional alias for {unwrap}.
function intoInt256(SD59x18 x) pure returns (int256 result) {
result = SD59x18.unwrap(x);
}
/// @notice Casts an SD59x18 number into SD1x18.
/// @dev Requirements:
/// - x must be greater than or equal to `uMIN_SD1x18`.
/// - x must be less than or equal to `uMAX_SD1x18`.
function intoSD1x18(SD59x18 x) pure returns (SD1x18 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < uMIN_SD1x18) {
revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Underflow(x);
}
if (xInt > uMAX_SD1x18) {
revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Overflow(x);
}
result = SD1x18.wrap(int64(xInt));
}
/// @notice Casts an SD59x18 number into UD2x18.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `uMAX_UD2x18`.
function intoUD2x18(SD59x18 x) pure returns (UD2x18 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Underflow(x);
}
if (xInt > int256(uint256(uMAX_UD2x18))) {
revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Overflow(x);
}
result = UD2x18.wrap(uint64(uint256(xInt)));
}
/// @notice Casts an SD59x18 number into UD60x18.
/// @dev Requirements:
/// - x must be positive.
function intoUD60x18(SD59x18 x) pure returns (UD60x18 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD59x18_IntoUD60x18_Underflow(x);
}
result = UD60x18.wrap(uint256(xInt));
}
/// @notice Casts an SD59x18 number into uint256.
/// @dev Requirements:
/// - x must be positive.
function intoUint256(SD59x18 x) pure returns (uint256 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD59x18_IntoUint256_Underflow(x);
}
result = uint256(xInt);
}
/// @notice Casts an SD59x18 number into uint128.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `uMAX_UINT128`.
function intoUint128(SD59x18 x) pure returns (uint128 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD59x18_IntoUint128_Underflow(x);
}
if (xInt > int256(uint256(MAX_UINT128))) {
revert CastingErrors.PRBMath_SD59x18_IntoUint128_Overflow(x);
}
result = uint128(uint256(xInt));
}
/// @notice Casts an SD59x18 number into uint40.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(SD59x18 x) pure returns (uint40 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD59x18_IntoUint40_Underflow(x);
}
if (xInt > int256(uint256(MAX_UINT40))) {
revert CastingErrors.PRBMath_SD59x18_IntoUint40_Overflow(x);
}
result = uint40(uint256(xInt));
}
/// @notice Alias for {wrap}.
function sd(int256 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(x);
}
/// @notice Alias for {wrap}.
function sd59x18(int256 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(x);
}
/// @notice Unwraps an SD59x18 number into int256.
function unwrap(SD59x18 x) pure returns (int256 result) {
result = SD59x18.unwrap(x);
}
/// @notice Wraps an int256 number into SD59x18.
function wrap(int256 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { SD59x18 } from "./ValueType.sol";
// NOTICE: the "u" prefix stands for "unwrapped".
/// @dev Euler's number as an SD59x18 number.
SD59x18 constant E = SD59x18.wrap(2_718281828459045235);
/// @dev The maximum input permitted in {exp}.
int256 constant uEXP_MAX_INPUT = 133_084258667509499440;
SD59x18 constant EXP_MAX_INPUT = SD59x18.wrap(uEXP_MAX_INPUT);
/// @dev The maximum input permitted in {exp2}.
int256 constant uEXP2_MAX_INPUT = 192e18 - 1;
SD59x18 constant EXP2_MAX_INPUT = SD59x18.wrap(uEXP2_MAX_INPUT);
/// @dev Half the UNIT number.
int256 constant uHALF_UNIT = 0.5e18;
SD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT);
/// @dev $log_2(10)$ as an SD59x18 number.
int256 constant uLOG2_10 = 3_321928094887362347;
SD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10);
/// @dev $log_2(e)$ as an SD59x18 number.
int256 constant uLOG2_E = 1_442695040888963407;
SD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E);
/// @dev The maximum value an SD59x18 number can have.
int256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967;
SD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18);
/// @dev The maximum whole value an SD59x18 number can have.
int256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000;
SD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18);
/// @dev The minimum value an SD59x18 number can have.
int256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968;
SD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18);
/// @dev The minimum whole value an SD59x18 number can have.
int256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000;
SD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18);
/// @dev PI as an SD59x18 number.
SD59x18 constant PI = SD59x18.wrap(3_141592653589793238);
/// @dev The unit number, which gives the decimal precision of SD59x18.
int256 constant uUNIT = 1e18;
SD59x18 constant UNIT = SD59x18.wrap(1e18);
/// @dev The unit number squared.
int256 constant uUNIT_SQUARED = 1e36;
SD59x18 constant UNIT_SQUARED = SD59x18.wrap(uUNIT_SQUARED);
/// @dev Zero as an SD59x18 number.
SD59x18 constant ZERO = SD59x18.wrap(0);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { uMAX_SD59x18, uMIN_SD59x18, uUNIT } from "./Constants.sol";
import { PRBMath_SD59x18_Convert_Overflow, PRBMath_SD59x18_Convert_Underflow } from "./Errors.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Converts a simple integer to SD59x18 by multiplying it by `UNIT`.
///
/// @dev Requirements:
/// - x must be greater than or equal to `MIN_SD59x18 / UNIT`.
/// - x must be less than or equal to `MAX_SD59x18 / UNIT`.
///
/// @param x The basic integer to convert.
/// @param result The same number converted to SD59x18.
function convert(int256 x) pure returns (SD59x18 result) {
if (x < uMIN_SD59x18 / uUNIT) {
revert PRBMath_SD59x18_Convert_Underflow(x);
}
if (x > uMAX_SD59x18 / uUNIT) {
revert PRBMath_SD59x18_Convert_Overflow(x);
}
unchecked {
result = SD59x18.wrap(x * uUNIT);
}
}
/// @notice Converts an SD59x18 number to a simple integer by dividing it by `UNIT`.
/// @dev The result is rounded toward zero.
/// @param x The SD59x18 number to convert.
/// @return result The same number as a simple integer.
function convert(SD59x18 x) pure returns (int256 result) {
result = SD59x18.unwrap(x) / uUNIT;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { SD59x18 } from "./ValueType.sol";
/// @notice Thrown when taking the absolute value of `MIN_SD59x18`.
error PRBMath_SD59x18_Abs_MinSD59x18();
/// @notice Thrown when ceiling a number overflows SD59x18.
error PRBMath_SD59x18_Ceil_Overflow(SD59x18 x);
/// @notice Thrown when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMath_SD59x18_Convert_Overflow(int256 x);
/// @notice Thrown when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMath_SD59x18_Convert_Underflow(int256 x);
/// @notice Thrown when dividing two numbers and one of them is `MIN_SD59x18`.
error PRBMath_SD59x18_Div_InputTooSmall();
/// @notice Thrown when dividing two numbers and one of the intermediary unsigned results overflows SD59x18.
error PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y);
/// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441.
error PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x);
/// @notice Thrown when taking the binary exponent of a base greater than 192e18.
error PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x);
/// @notice Thrown when flooring a number underflows SD59x18.
error PRBMath_SD59x18_Floor_Underflow(SD59x18 x);
/// @notice Thrown when taking the geometric mean of two numbers and their product is negative.
error PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y);
/// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows SD59x18.
error PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.
error PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.
error PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.
error PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.
error PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD60x18.
error PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.
error PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.
error PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint256.
error PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.
error PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.
error PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x);
/// @notice Thrown when taking the logarithm of a number less than or equal to zero.
error PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x);
/// @notice Thrown when multiplying two numbers and one of the inputs is `MIN_SD59x18`.
error PRBMath_SD59x18_Mul_InputTooSmall();
/// @notice Thrown when multiplying two numbers and the intermediary absolute result overflows SD59x18.
error PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y);
/// @notice Thrown when raising a number to a power and hte intermediary absolute result overflows SD59x18.
error PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y);
/// @notice Thrown when taking the square root of a negative number.
error PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x);
/// @notice Thrown when the calculating the square root overflows SD59x18.
error PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { wrap } from "./Casting.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Implements the checked addition operation (+) in the SD59x18 type.
function add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
return wrap(x.unwrap() + y.unwrap());
}
/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.
function and(SD59x18 x, int256 bits) pure returns (SD59x18 result) {
return wrap(x.unwrap() & bits);
}
/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.
function and2(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
return wrap(x.unwrap() & y.unwrap());
}
/// @notice Implements the equal (=) operation in the SD59x18 type.
function eq(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = x.unwrap() == y.unwrap();
}
/// @notice Implements the greater than operation (>) in the SD59x18 type.
function gt(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = x.unwrap() > y.unwrap();
}
/// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type.
function gte(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = x.unwrap() >= y.unwrap();
}
/// @notice Implements a zero comparison check function in the SD59x18 type.
function isZero(SD59x18 x) pure returns (bool result) {
result = x.unwrap() == 0;
}
/// @notice Implements the left shift operation (<<) in the SD59x18 type.
function lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {
result = wrap(x.unwrap() << bits);
}
/// @notice Implements the lower than operation (<) in the SD59x18 type.
function lt(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = x.unwrap() < y.unwrap();
}
/// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type.
function lte(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = x.unwrap() <= y.unwrap();
}
/// @notice Implements the unchecked modulo operation (%) in the SD59x18 type.
function mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(x.unwrap() % y.unwrap());
}
/// @notice Implements the not equal operation (!=) in the SD59x18 type.
function neq(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = x.unwrap() != y.unwrap();
}
/// @notice Implements the NOT (~) bitwise operation in the SD59x18 type.
function not(SD59x18 x) pure returns (SD59x18 result) {
result = wrap(~x.unwrap());
}
/// @notice Implements the OR (|) bitwise operation in the SD59x18 type.
function or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(x.unwrap() | y.unwrap());
}
/// @notice Implements the right shift operation (>>) in the SD59x18 type.
function rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {
result = wrap(x.unwrap() >> bits);
}
/// @notice Implements the checked subtraction operation (-) in the SD59x18 type.
function sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(x.unwrap() - y.unwrap());
}
/// @notice Implements the checked unary minus operation (-) in the SD59x18 type.
function unary(SD59x18 x) pure returns (SD59x18 result) {
result = wrap(-x.unwrap());
}
/// @notice Implements the unchecked addition operation (+) in the SD59x18 type.
function uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
unchecked {
result = wrap(x.unwrap() + y.unwrap());
}
}
/// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type.
function uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
unchecked {
result = wrap(x.unwrap() - y.unwrap());
}
}
/// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type.
function uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) {
unchecked {
result = wrap(-x.unwrap());
}
}
/// @notice Implements the XOR (^) bitwise operation in the SD59x18 type.
function xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(x.unwrap() ^ y.unwrap());
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "../Common.sol" as Common;
import "./Errors.sol" as Errors;
import {
uEXP_MAX_INPUT,
uEXP2_MAX_INPUT,
uHALF_UNIT,
uLOG2_10,
uLOG2_E,
uMAX_SD59x18,
uMAX_WHOLE_SD59x18,
uMIN_SD59x18,
uMIN_WHOLE_SD59x18,
UNIT,
uUNIT,
uUNIT_SQUARED,
ZERO
} from "./Constants.sol";
import { wrap } from "./Helpers.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Calculates the absolute value of x.
///
/// @dev Requirements:
/// - x must be greater than `MIN_SD59x18`.
///
/// @param x The SD59x18 number for which to calculate the absolute value.
/// @param result The absolute value of x as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function abs(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt == uMIN_SD59x18) {
revert Errors.PRBMath_SD59x18_Abs_MinSD59x18();
}
result = xInt < 0 ? wrap(-xInt) : x;
}
/// @notice Calculates the arithmetic average of x and y.
///
/// @dev Notes:
/// - The result is rounded toward zero.
///
/// @param x The first operand as an SD59x18 number.
/// @param y The second operand as an SD59x18 number.
/// @return result The arithmetic average as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
unchecked {
// This operation is equivalent to `x / 2 + y / 2`, and it can never overflow.
int256 sum = (xInt >> 1) + (yInt >> 1);
if (sum < 0) {
// If at least one of x and y is odd, add 1 to the result, because shifting negative numbers to the right
// rounds toward negative infinity. The right part is equivalent to `sum + (x % 2 == 1 || y % 2 == 1)`.
assembly ("memory-safe") {
result := add(sum, and(or(xInt, yInt), 1))
}
} else {
// Add 1 if both x and y are odd to account for the double 0.5 remainder truncated after shifting.
result = wrap(sum + (xInt & yInt & 1));
}
}
}
/// @notice Yields the smallest whole number greater than or equal to x.
///
/// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be less than or equal to `MAX_WHOLE_SD59x18`.
///
/// @param x The SD59x18 number to ceil.
/// @param result The smallest whole number greater than or equal to x, as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function ceil(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt > uMAX_WHOLE_SD59x18) {
revert Errors.PRBMath_SD59x18_Ceil_Overflow(x);
}
int256 remainder = xInt % uUNIT;
if (remainder == 0) {
result = x;
} else {
unchecked {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.
int256 resultInt = xInt - remainder;
if (xInt > 0) {
resultInt += uUNIT;
}
result = wrap(resultInt);
}
}
}
/// @notice Divides two SD59x18 numbers, returning a new SD59x18 number.
///
/// @dev This is an extension of {Common.mulDiv} for signed numbers, which works by computing the signs and the absolute
/// values separately.
///
/// Notes:
/// - Refer to the notes in {Common.mulDiv}.
/// - The result is rounded toward zero.
///
/// Requirements:
/// - Refer to the requirements in {Common.mulDiv}.
/// - None of the inputs can be `MIN_SD59x18`.
/// - The denominator must not be zero.
/// - The result must fit in SD59x18.
///
/// @param x The numerator as an SD59x18 number.
/// @param y The denominator as an SD59x18 number.
/// @param result The quotient as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {
revert Errors.PRBMath_SD59x18_Div_InputTooSmall();
}
// Get hold of the absolute values of x and y.
uint256 xAbs;
uint256 yAbs;
unchecked {
xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);
yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);
}
// Compute the absolute value (x*UNIT÷y). The resulting value must fit in SD59x18.
uint256 resultAbs = Common.mulDiv(xAbs, uint256(uUNIT), yAbs);
if (resultAbs > uint256(uMAX_SD59x18)) {
revert Errors.PRBMath_SD59x18_Div_Overflow(x, y);
}
// Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for
// negative, 0 for positive or zero).
bool sameSign = (xInt ^ yInt) > -1;
// If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.
unchecked {
result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));
}
}
/// @notice Calculates the natural exponent of x using the following formula:
///
/// $$
/// e^x = 2^{x * log_2{e}}
/// $$
///
/// @dev Notes:
/// - Refer to the notes in {exp2}.
///
/// Requirements:
/// - Refer to the requirements in {exp2}.
/// - x must be less than 133_084258667509499441.
///
/// @param x The exponent as an SD59x18 number.
/// @return result The result as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function exp(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
// This check prevents values greater than 192e18 from being passed to {exp2}.
if (xInt > uEXP_MAX_INPUT) {
revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x);
}
unchecked {
// Inline the fixed-point multiplication to save gas.
int256 doubleUnitProduct = xInt * uLOG2_E;
result = exp2(wrap(doubleUnitProduct / uUNIT));
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method using the following formula:
///
/// $$
/// 2^{-x} = \frac{1}{2^x}
/// $$
///
/// @dev See https://ethereum.stackexchange.com/q/79903/24693.
///
/// Notes:
/// - If x is less than -59_794705707972522261, the result is zero.
///
/// Requirements:
/// - x must be less than 192e18.
/// - The result must fit in SD59x18.
///
/// @param x The exponent as an SD59x18 number.
/// @return result The result as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function exp2(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt < 0) {
// The inverse of any number less than this is truncated to zero.
if (xInt < -59_794705707972522261) {
return ZERO;
}
unchecked {
// Inline the fixed-point inversion to save gas.
result = wrap(uUNIT_SQUARED / exp2(wrap(-xInt)).unwrap());
}
} else {
// Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.
if (xInt > uEXP2_MAX_INPUT) {
revert Errors.PRBMath_SD59x18_Exp2_InputTooBig(x);
}
unchecked {
// Convert x to the 192.64-bit fixed-point format.
uint256 x_192x64 = uint256((xInt << 64) / uUNIT);
// It is safe to cast the result to int256 due to the checks above.
result = wrap(int256(Common.exp2(x_192x64)));
}
}
}
/// @notice Yields the greatest whole number less than or equal to x.
///
/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional
/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be greater than or equal to `MIN_WHOLE_SD59x18`.
///
/// @param x The SD59x18 number to floor.
/// @param result The greatest whole number less than or equal to x, as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function floor(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt < uMIN_WHOLE_SD59x18) {
revert Errors.PRBMath_SD59x18_Floor_Underflow(x);
}
int256 remainder = xInt % uUNIT;
if (remainder == 0) {
result = x;
} else {
unchecked {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.
int256 resultInt = xInt - remainder;
if (xInt < 0) {
resultInt -= uUNIT;
}
result = wrap(resultInt);
}
}
}
/// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right.
/// of the radix point for negative numbers.
/// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part
/// @param x The SD59x18 number to get the fractional part of.
/// @param result The fractional part of x as an SD59x18 number.
function frac(SD59x18 x) pure returns (SD59x18 result) {
result = wrap(x.unwrap() % uUNIT);
}
/// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$.
///
/// @dev Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - x * y must fit in SD59x18.
/// - x * y must not be negative, since complex numbers are not supported.
///
/// @param x The first operand as an SD59x18 number.
/// @param y The second operand as an SD59x18 number.
/// @return result The result as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
if (xInt == 0 || yInt == 0) {
return ZERO;
}
unchecked {
// Equivalent to `xy / x != y`. Checking for overflow this way is faster than letting Solidity do it.
int256 xyInt = xInt * yInt;
if (xyInt / xInt != yInt) {
revert Errors.PRBMath_SD59x18_Gm_Overflow(x, y);
}
// The product must not be negative, since complex numbers are not supported.
if (xyInt < 0) {
revert Errors.PRBMath_SD59x18_Gm_NegativeProduct(x, y);
}
// We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`
// during multiplication. See the comments in {Common.sqrt}.
uint256 resultUint = Common.sqrt(uint256(xyInt));
result = wrap(int256(resultUint));
}
}
/// @notice Calculates the inverse of x.
///
/// @dev Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - x must not be zero.
///
/// @param x The SD59x18 number for which to calculate the inverse.
/// @return result The inverse as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function inv(SD59x18 x) pure returns (SD59x18 result) {
result = wrap(uUNIT_SQUARED / x.unwrap());
}
/// @notice Calculates the natural logarithm of x using the following formula:
///
/// $$
/// ln{x} = log_2{x} / log_2{e}
/// $$
///
/// @dev Notes:
/// - Refer to the notes in {log2}.
/// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.
///
/// Requirements:
/// - Refer to the requirements in {log2}.
///
/// @param x The SD59x18 number for which to calculate the natural logarithm.
/// @return result The natural logarithm as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function ln(SD59x18 x) pure returns (SD59x18 result) {
// Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that
// {log2} can return is ~195_205294292027477728.
result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);
}
/// @notice Calculates the common logarithm of x using the following formula:
///
/// $$
/// log_{10}{x} = log_2{x} / log_2{10}
/// $$
///
/// However, if x is an exact power of ten, a hard coded value is returned.
///
/// @dev Notes:
/// - Refer to the notes in {log2}.
///
/// Requirements:
/// - Refer to the requirements in {log2}.
///
/// @param x The SD59x18 number for which to calculate the common logarithm.
/// @return result The common logarithm as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function log10(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt < 0) {
revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);
}
// Note that the `mul` in this block is the standard multiplication operation, not {SD59x18.mul}.
// prettier-ignore
assembly ("memory-safe") {
switch x
case 1 { result := mul(uUNIT, sub(0, 18)) }
case 10 { result := mul(uUNIT, sub(1, 18)) }
case 100 { result := mul(uUNIT, sub(2, 18)) }
case 1000 { result := mul(uUNIT, sub(3, 18)) }
case 10000 { result := mul(uUNIT, sub(4, 18)) }
case 100000 { result := mul(uUNIT, sub(5, 18)) }
case 1000000 { result := mul(uUNIT, sub(6, 18)) }
case 10000000 { result := mul(uUNIT, sub(7, 18)) }
case 100000000 { result := mul(uUNIT, sub(8, 18)) }
case 1000000000 { result := mul(uUNIT, sub(9, 18)) }
case 10000000000 { result := mul(uUNIT, sub(10, 18)) }
case 100000000000 { result := mul(uUNIT, sub(11, 18)) }
case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }
case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }
case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }
case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }
case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }
case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := uUNIT }
case 100000000000000000000 { result := mul(uUNIT, 2) }
case 1000000000000000000000 { result := mul(uUNIT, 3) }
case 10000000000000000000000 { result := mul(uUNIT, 4) }
case 100000000000000000000000 { result := mul(uUNIT, 5) }
case 1000000000000000000000000 { result := mul(uUNIT, 6) }
case 10000000000000000000000000 { result := mul(uUNIT, 7) }
case 100000000000000000000000000 { result := mul(uUNIT, 8) }
case 1000000000000000000000000000 { result := mul(uUNIT, 9) }
case 10000000000000000000000000000 { result := mul(uUNIT, 10) }
case 100000000000000000000000000000 { result := mul(uUNIT, 11) }
case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }
case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }
case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }
case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }
case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }
case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }
case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }
case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }
case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }
case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }
case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }
case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }
default { result := uMAX_SD59x18 }
}
if (result.unwrap() == uMAX_SD59x18) {
unchecked {
// Inline the fixed-point division to save gas.
result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);
}
}
}
/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:
///
/// $$
/// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2)
/// $$
///
/// For $0 \leq x \lt 1$, the input is inverted:
///
/// $$
/// log_2{x} = -log_2{\frac{1}{x}}
/// $$
///
/// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation.
///
/// Notes:
/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.
///
/// Requirements:
/// - x must be greater than zero.
///
/// @param x The SD59x18 number for which to calculate the binary logarithm.
/// @return result The binary logarithm as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function log2(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt <= 0) {
revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);
}
unchecked {
int256 sign;
if (xInt >= uUNIT) {
sign = 1;
} else {
sign = -1;
// Inline the fixed-point inversion to save gas.
xInt = uUNIT_SQUARED / xInt;
}
// Calculate the integer part of the logarithm.
uint256 n = Common.msb(uint256(xInt / uUNIT));
// This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow
// because n is at most 255, `UNIT` is 1e18, and the sign is either 1 or -1.
int256 resultInt = int256(n) * uUNIT;
// Calculate $y = x * 2^{-n}$.
int256 y = xInt >> n;
// If y is the unit number, the fractional part is zero.
if (y == uUNIT) {
return wrap(resultInt * sign);
}
// Calculate the fractional part via the iterative approximation.
// The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.
int256 DOUBLE_UNIT = 2e18;
for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {
y = (y * y) / uUNIT;
// Is y^2 >= 2e18 and so in the range [2e18, 4e18)?
if (y >= DOUBLE_UNIT) {
// Add the 2^{-m} factor to the logarithm.
resultInt = resultInt + delta;
// Halve y, which corresponds to z/2 in the Wikipedia article.
y >>= 1;
}
}
resultInt *= sign;
result = wrap(resultInt);
}
}
/// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number.
///
/// @dev Notes:
/// - Refer to the notes in {Common.mulDiv18}.
///
/// Requirements:
/// - Refer to the requirements in {Common.mulDiv18}.
/// - None of the inputs can be `MIN_SD59x18`.
/// - The result must fit in SD59x18.
///
/// @param x The multiplicand as an SD59x18 number.
/// @param y The multiplier as an SD59x18 number.
/// @return result The product as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {
revert Errors.PRBMath_SD59x18_Mul_InputTooSmall();
}
// Get hold of the absolute values of x and y.
uint256 xAbs;
uint256 yAbs;
unchecked {
xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);
yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);
}
// Compute the absolute value (x*y÷UNIT). The resulting value must fit in SD59x18.
uint256 resultAbs = Common.mulDiv18(xAbs, yAbs);
if (resultAbs > uint256(uMAX_SD59x18)) {
revert Errors.PRBMath_SD59x18_Mul_Overflow(x, y);
}
// Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for
// negative, 0 for positive or zero).
bool sameSign = (xInt ^ yInt) > -1;
// If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.
unchecked {
result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));
}
}
/// @notice Raises x to the power of y using the following formula:
///
/// $$
/// x^y = 2^{log_2{x} * y}
/// $$
///
/// @dev Notes:
/// - Refer to the notes in {exp2}, {log2}, and {mul}.
/// - Returns `UNIT` for 0^0.
///
/// Requirements:
/// - Refer to the requirements in {exp2}, {log2}, and {mul}.
///
/// @param x The base as an SD59x18 number.
/// @param y Exponent to raise x to, as an SD59x18 number
/// @return result x raised to power y, as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
// If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.
if (xInt == 0) {
return yInt == 0 ? UNIT : ZERO;
}
// If x is `UNIT`, the result is always `UNIT`.
else if (xInt == uUNIT) {
return UNIT;
}
// If y is zero, the result is always `UNIT`.
if (yInt == 0) {
return UNIT;
}
// If y is `UNIT`, the result is always x.
else if (yInt == uUNIT) {
return x;
}
// Calculate the result using the formula.
result = exp2(mul(log2(x), y));
}
/// @notice Raises x (an SD59x18 number) to the power y (an unsigned basic integer) using the well-known
/// algorithm "exponentiation by squaring".
///
/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.
///
/// Notes:
/// - Refer to the notes in {Common.mulDiv18}.
/// - Returns `UNIT` for 0^0.
///
/// Requirements:
/// - Refer to the requirements in {abs} and {Common.mulDiv18}.
/// - The result must fit in SD59x18.
///
/// @param x The base as an SD59x18 number.
/// @param y The exponent as a uint256.
/// @return result The result as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) {
uint256 xAbs = uint256(abs(x).unwrap());
// Calculate the first iteration of the loop in advance.
uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT);
// Equivalent to `for(y /= 2; y > 0; y /= 2)`.
uint256 yAux = y;
for (yAux >>= 1; yAux > 0; yAux >>= 1) {
xAbs = Common.mulDiv18(xAbs, xAbs);
// Equivalent to `y % 2 == 1`.
if (yAux & 1 > 0) {
resultAbs = Common.mulDiv18(resultAbs, xAbs);
}
}
// The result must fit in SD59x18.
if (resultAbs > uint256(uMAX_SD59x18)) {
revert Errors.PRBMath_SD59x18_Powu_Overflow(x, y);
}
unchecked {
// Is the base negative and the exponent odd? If yes, the result should be negative.
int256 resultInt = int256(resultAbs);
bool isNegative = x.unwrap() < 0 && y & 1 == 1;
if (isNegative) {
resultInt = -resultInt;
}
result = wrap(resultInt);
}
}
/// @notice Calculates the square root of x using the Babylonian method.
///
/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Notes:
/// - Only the positive root is returned.
/// - The result is rounded toward zero.
///
/// Requirements:
/// - x cannot be negative, since complex numbers are not supported.
/// - x must be less than `MAX_SD59x18 / UNIT`.
///
/// @param x The SD59x18 number for which to calculate the square root.
/// @return result The result as an SD59x18 number.
/// @custom:smtchecker abstract-function-nondet
function sqrt(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt < 0) {
revert Errors.PRBMath_SD59x18_Sqrt_NegativeInput(x);
}
if (xInt > uMAX_SD59x18 / uUNIT) {
revert Errors.PRBMath_SD59x18_Sqrt_Overflow(x);
}
unchecked {
// Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two SD59x18 numbers.
// In this case, the two numbers are both the square root.
uint256 resultUint = Common.sqrt(uint256(xInt * uUNIT));
result = wrap(int256(resultUint));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./Casting.sol" as Casting;
import "./Helpers.sol" as Helpers;
import "./Math.sol" as Math;
/// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18
/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity
/// type int256.
type SD59x18 is int256;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using {
Casting.intoInt256,
Casting.intoSD1x18,
Casting.intoUD2x18,
Casting.intoUD60x18,
Casting.intoUint256,
Casting.intoUint128,
Casting.intoUint40,
Casting.unwrap
} for SD59x18 global;
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
using {
Math.abs,
Math.avg,
Math.ceil,
Math.div,
Math.exp,
Math.exp2,
Math.floor,
Math.frac,
Math.gm,
Math.inv,
Math.log10,
Math.log2,
Math.ln,
Math.mul,
Math.pow,
Math.powu,
Math.sqrt
} for SD59x18 global;
/*//////////////////////////////////////////////////////////////////////////
HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
using {
Helpers.add,
Helpers.and,
Helpers.eq,
Helpers.gt,
Helpers.gte,
Helpers.isZero,
Helpers.lshift,
Helpers.lt,
Helpers.lte,
Helpers.mod,
Helpers.neq,
Helpers.not,
Helpers.or,
Helpers.rshift,
Helpers.sub,
Helpers.uncheckedAdd,
Helpers.uncheckedSub,
Helpers.uncheckedUnary,
Helpers.xor
} for SD59x18 global;
/*//////////////////////////////////////////////////////////////////////////
OPERATORS
//////////////////////////////////////////////////////////////////////////*/
// The global "using for" directive makes it possible to use these operators on the SD59x18 type.
using {
Helpers.add as +,
Helpers.and2 as &,
Math.div as /,
Helpers.eq as ==,
Helpers.gt as >,
Helpers.gte as >=,
Helpers.lt as <,
Helpers.lte as <=,
Helpers.mod as %,
Math.mul as *,
Helpers.neq as !=,
Helpers.not as ~,
Helpers.or as |,
Helpers.sub as -,
Helpers.unary as -,
Helpers.xor as ^
} for SD59x18 global;// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.19;
import { SD59x18, wrap } from "prb-math/SD59x18.sol";
library SafeSD59x18 {
function safeExp(SD59x18 x) internal pure returns (SD59x18) {
if (x.unwrap() < -41.45e18) {
return wrap(0);
}
return x.exp();
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
// Common.sol
//
// Common mathematical functions needed by both SD59x18 and UD60x18. Note that these global functions do not
// always operate with SD59x18 and UD60x18 numbers.
/*//////////////////////////////////////////////////////////////////////////
CUSTOM ERRORS
//////////////////////////////////////////////////////////////////////////*/
/// @notice Thrown when the resultant value in {mulDiv} overflows uint256.
error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator);
/// @notice Thrown when the resultant value in {mulDiv18} overflows uint256.
error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y);
/// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`.
error PRBMath_MulDivSigned_InputTooSmall();
/// @notice Thrown when the resultant value in {mulDivSigned} overflows int256.
error PRBMath_MulDivSigned_Overflow(int256 x, int256 y);
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/
/// @dev The maximum value a uint128 number can have.
uint128 constant MAX_UINT128 = type(uint128).max;
/// @dev The maximum value a uint40 number can have.
uint40 constant MAX_UINT40 = type(uint40).max;
/// @dev The unit number, which the decimal precision of the fixed-point types.
uint256 constant UNIT = 1e18;
/// @dev The unit number inverted mod 2^256.
uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281;
/// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant
/// bit in the binary representation of `UNIT`.
uint256 constant UNIT_LPOTD = 262144;
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/// @notice Calculates the binary exponent of x using the binary fraction method.
/// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693.
/// @param x The exponent as an unsigned 192.64-bit fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
/// @custom:smtchecker abstract-function-nondet
function exp2(uint256 x) pure returns (uint256 result) {
unchecked {
// Start from 0.5 in the 192.64-bit fixed-point format.
result = 0x800000000000000000000000000000000000000000000000;
// The following logic multiplies the result by $\sqrt{2^{-i}}$ when the bit at position i is 1. Key points:
//
// 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65.
// 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing
// a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1,
// we know that `x & 0xFF` is also 1.
if (x & 0xFF00000000000000 > 0) {
if (x & 0x8000000000000000 > 0) {
result = (result * 0x16A09E667F3BCC909) >> 64;
}
if (x & 0x4000000000000000 > 0) {
result = (result * 0x1306FE0A31B7152DF) >> 64;
}
if (x & 0x2000000000000000 > 0) {
result = (result * 0x1172B83C7D517ADCE) >> 64;
}
if (x & 0x1000000000000000 > 0) {
result = (result * 0x10B5586CF9890F62A) >> 64;
}
if (x & 0x800000000000000 > 0) {
result = (result * 0x1059B0D31585743AE) >> 64;
}
if (x & 0x400000000000000 > 0) {
result = (result * 0x102C9A3E778060EE7) >> 64;
}
if (x & 0x200000000000000 > 0) {
result = (result * 0x10163DA9FB33356D8) >> 64;
}
if (x & 0x100000000000000 > 0) {
result = (result * 0x100B1AFA5ABCBED61) >> 64;
}
}
if (x & 0xFF000000000000 > 0) {
if (x & 0x80000000000000 > 0) {
result = (result * 0x10058C86DA1C09EA2) >> 64;
}
if (x & 0x40000000000000 > 0) {
result = (result * 0x1002C605E2E8CEC50) >> 64;
}
if (x & 0x20000000000000 > 0) {
result = (result * 0x100162F3904051FA1) >> 64;
}
if (x & 0x10000000000000 > 0) {
result = (result * 0x1000B175EFFDC76BA) >> 64;
}
if (x & 0x8000000000000 > 0) {
result = (result * 0x100058BA01FB9F96D) >> 64;
}
if (x & 0x4000000000000 > 0) {
result = (result * 0x10002C5CC37DA9492) >> 64;
}
if (x & 0x2000000000000 > 0) {
result = (result * 0x1000162E525EE0547) >> 64;
}
if (x & 0x1000000000000 > 0) {
result = (result * 0x10000B17255775C04) >> 64;
}
}
if (x & 0xFF0000000000 > 0) {
if (x & 0x800000000000 > 0) {
result = (result * 0x1000058B91B5BC9AE) >> 64;
}
if (x & 0x400000000000 > 0) {
result = (result * 0x100002C5C89D5EC6D) >> 64;
}
if (x & 0x200000000000 > 0) {
result = (result * 0x10000162E43F4F831) >> 64;
}
if (x & 0x100000000000 > 0) {
result = (result * 0x100000B1721BCFC9A) >> 64;
}
if (x & 0x80000000000 > 0) {
result = (result * 0x10000058B90CF1E6E) >> 64;
}
if (x & 0x40000000000 > 0) {
result = (result * 0x1000002C5C863B73F) >> 64;
}
if (x & 0x20000000000 > 0) {
result = (result * 0x100000162E430E5A2) >> 64;
}
if (x & 0x10000000000 > 0) {
result = (result * 0x1000000B172183551) >> 64;
}
}
if (x & 0xFF00000000 > 0) {
if (x & 0x8000000000 > 0) {
result = (result * 0x100000058B90C0B49) >> 64;
}
if (x & 0x4000000000 > 0) {
result = (result * 0x10000002C5C8601CC) >> 64;
}
if (x & 0x2000000000 > 0) {
result = (result * 0x1000000162E42FFF0) >> 64;
}
if (x & 0x1000000000 > 0) {
result = (result * 0x10000000B17217FBB) >> 64;
}
if (x & 0x800000000 > 0) {
result = (result * 0x1000000058B90BFCE) >> 64;
}
if (x & 0x400000000 > 0) {
result = (result * 0x100000002C5C85FE3) >> 64;
}
if (x & 0x200000000 > 0) {
result = (result * 0x10000000162E42FF1) >> 64;
}
if (x & 0x100000000 > 0) {
result = (result * 0x100000000B17217F8) >> 64;
}
}
if (x & 0xFF000000 > 0) {
if (x & 0x80000000 > 0) {
result = (result * 0x10000000058B90BFC) >> 64;
}
if (x & 0x40000000 > 0) {
result = (result * 0x1000000002C5C85FE) >> 64;
}
if (x & 0x20000000 > 0) {
result = (result * 0x100000000162E42FF) >> 64;
}
if (x & 0x10000000 > 0) {
result = (result * 0x1000000000B17217F) >> 64;
}
if (x & 0x8000000 > 0) {
result = (result * 0x100000000058B90C0) >> 64;
}
if (x & 0x4000000 > 0) {
result = (result * 0x10000000002C5C860) >> 64;
}
if (x & 0x2000000 > 0) {
result = (result * 0x1000000000162E430) >> 64;
}
if (x & 0x1000000 > 0) {
result = (result * 0x10000000000B17218) >> 64;
}
}
if (x & 0xFF0000 > 0) {
if (x & 0x800000 > 0) {
result = (result * 0x1000000000058B90C) >> 64;
}
if (x & 0x400000 > 0) {
result = (result * 0x100000000002C5C86) >> 64;
}
if (x & 0x200000 > 0) {
result = (result * 0x10000000000162E43) >> 64;
}
if (x & 0x100000 > 0) {
result = (result * 0x100000000000B1721) >> 64;
}
if (x & 0x80000 > 0) {
result = (result * 0x10000000000058B91) >> 64;
}
if (x & 0x40000 > 0) {
result = (result * 0x1000000000002C5C8) >> 64;
}
if (x & 0x20000 > 0) {
result = (result * 0x100000000000162E4) >> 64;
}
if (x & 0x10000 > 0) {
result = (result * 0x1000000000000B172) >> 64;
}
}
if (x & 0xFF00 > 0) {
if (x & 0x8000 > 0) {
result = (result * 0x100000000000058B9) >> 64;
}
if (x & 0x4000 > 0) {
result = (result * 0x10000000000002C5D) >> 64;
}
if (x & 0x2000 > 0) {
result = (result * 0x1000000000000162E) >> 64;
}
if (x & 0x1000 > 0) {
result = (result * 0x10000000000000B17) >> 64;
}
if (x & 0x800 > 0) {
result = (result * 0x1000000000000058C) >> 64;
}
if (x & 0x400 > 0) {
result = (result * 0x100000000000002C6) >> 64;
}
if (x & 0x200 > 0) {
result = (result * 0x10000000000000163) >> 64;
}
if (x & 0x100 > 0) {
result = (result * 0x100000000000000B1) >> 64;
}
}
if (x & 0xFF > 0) {
if (x & 0x80 > 0) {
result = (result * 0x10000000000000059) >> 64;
}
if (x & 0x40 > 0) {
result = (result * 0x1000000000000002C) >> 64;
}
if (x & 0x20 > 0) {
result = (result * 0x10000000000000016) >> 64;
}
if (x & 0x10 > 0) {
result = (result * 0x1000000000000000B) >> 64;
}
if (x & 0x8 > 0) {
result = (result * 0x10000000000000006) >> 64;
}
if (x & 0x4 > 0) {
result = (result * 0x10000000000000003) >> 64;
}
if (x & 0x2 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
if (x & 0x1 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
}
// In the code snippet below, two operations are executed simultaneously:
//
// 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1
// accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192.
// 2. The result is then converted to an unsigned 60.18-decimal fixed-point format.
//
// The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the,
// integer part, $2^n$.
result *= UNIT;
result >>= (191 - (x >> 64));
}
}
/// @notice Finds the zero-based index of the first 1 in the binary representation of x.
///
/// @dev See the note on "msb" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set
///
/// Each step in this implementation is equivalent to this high-level code:
///
/// ```solidity
/// if (x >= 2 ** 128) {
/// x >>= 128;
/// result += 128;
/// }
/// ```
///
/// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here:
/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948
///
/// The Yul instructions used below are:
///
/// - "gt" is "greater than"
/// - "or" is the OR bitwise operator
/// - "shl" is "shift left"
/// - "shr" is "shift right"
///
/// @param x The uint256 number for which to find the index of the most significant bit.
/// @return result The index of the most significant bit as a uint256.
/// @custom:smtchecker abstract-function-nondet
function msb(uint256 x) pure returns (uint256 result) {
// 2^128
assembly ("memory-safe") {
let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^64
assembly ("memory-safe") {
let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^32
assembly ("memory-safe") {
let factor := shl(5, gt(x, 0xFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^16
assembly ("memory-safe") {
let factor := shl(4, gt(x, 0xFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^8
assembly ("memory-safe") {
let factor := shl(3, gt(x, 0xFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^4
assembly ("memory-safe") {
let factor := shl(2, gt(x, 0xF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^2
assembly ("memory-safe") {
let factor := shl(1, gt(x, 0x3))
x := shr(factor, x)
result := or(result, factor)
}
// 2^1
// No need to shift x any more.
assembly ("memory-safe") {
let factor := gt(x, 0x1)
result := or(result, factor)
}
}
/// @notice Calculates x*y÷denominator with 512-bit precision.
///
/// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
///
/// Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - The denominator must not be zero.
/// - The result must fit in uint256.
///
/// @param x The multiplicand as a uint256.
/// @param y The multiplier as a uint256.
/// @param denominator The divisor as a uint256.
/// @return result The result as a uint256.
/// @custom:smtchecker abstract-function-nondet
function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly ("memory-safe") {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
unchecked {
return prod0 / denominator;
}
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (prod1 >= denominator) {
revert PRBMath_MulDiv_Overflow(x, y, denominator);
}
////////////////////////////////////////////////////////////////////////////
// 512 by 256 division
////////////////////////////////////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using the mulmod Yul instruction.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512-bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
unchecked {
// Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow
// because the denominator cannot be zero at this point in the function execution. The result is always >= 1.
// For more detail, see https://cs.stackexchange.com/q/138556/92363.
uint256 lpotdod = denominator & (~denominator + 1);
uint256 flippedLpotdod;
assembly ("memory-safe") {
// Factor powers of two out of denominator.
denominator := div(denominator, lpotdod)
// Divide [prod1 prod0] by lpotdod.
prod0 := div(prod0, lpotdod)
// Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one.
// `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits.
// However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693
flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * flippedLpotdod;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
}
}
/// @notice Calculates x*y÷1e18 with 512-bit precision.
///
/// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18.
///
/// Notes:
/// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}.
/// - The result is rounded toward zero.
/// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations:
///
/// $$
/// \begin{cases}
/// x * y = MAX\_UINT256 * UNIT \\
/// (x * y) \% UNIT \geq \frac{UNIT}{2}
/// \end{cases}
/// $$
///
/// Requirements:
/// - Refer to the requirements in {mulDiv}.
/// - The result must fit in uint256.
///
/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
/// @custom:smtchecker abstract-function-nondet
function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly ("memory-safe") {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
unchecked {
return prod0 / UNIT;
}
}
if (prod1 >= UNIT) {
revert PRBMath_MulDiv18_Overflow(x, y);
}
uint256 remainder;
assembly ("memory-safe") {
remainder := mulmod(x, y, UNIT)
result :=
mul(
or(
div(sub(prod0, remainder), UNIT_LPOTD),
mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1))
),
UNIT_INVERSE
)
}
}
/// @notice Calculates x*y÷denominator with 512-bit precision.
///
/// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately.
///
/// Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - Refer to the requirements in {mulDiv}.
/// - None of the inputs can be `type(int256).min`.
/// - The result must fit in int256.
///
/// @param x The multiplicand as an int256.
/// @param y The multiplier as an int256.
/// @param denominator The divisor as an int256.
/// @return result The result as an int256.
/// @custom:smtchecker abstract-function-nondet
function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) {
if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
revert PRBMath_MulDivSigned_InputTooSmall();
}
// Get hold of the absolute values of x, y and the denominator.
uint256 xAbs;
uint256 yAbs;
uint256 dAbs;
unchecked {
xAbs = x < 0 ? uint256(-x) : uint256(x);
yAbs = y < 0 ? uint256(-y) : uint256(y);
dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator);
}
// Compute the absolute value of x*y÷denominator. The result must fit in int256.
uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs);
if (resultAbs > uint256(type(int256).max)) {
revert PRBMath_MulDivSigned_Overflow(x, y);
}
// Get the signs of x, y and the denominator.
uint256 sx;
uint256 sy;
uint256 sd;
assembly ("memory-safe") {
// "sgt" is the "signed greater than" assembly instruction and "sub(0,1)" is -1 in two's complement.
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
sd := sgt(denominator, sub(0, 1))
}
// XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs.
// If there are, the result should be negative. Otherwise, it should be positive.
unchecked {
result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs);
}
}
/// @notice Calculates the square root of x using the Babylonian method.
///
/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Notes:
/// - If x is not a perfect square, the result is rounded down.
/// - Credits to OpenZeppelin for the explanations in comments below.
///
/// @param x The uint256 number for which to calculate the square root.
/// @return result The result as a uint256.
/// @custom:smtchecker abstract-function-nondet
function sqrt(uint256 x) pure returns (uint256 result) {
if (x == 0) {
return 0;
}
// For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x.
//
// We know that the "msb" (most significant bit) of x is a power of 2 such that we have:
//
// $$
// msb(x) <= x <= 2*msb(x)$
// $$
//
// We write $msb(x)$ as $2^k$, and we get:
//
// $$
// k = log_2(x)
// $$
//
// Thus, we can write the initial inequality as:
//
// $$
// 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\
// sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\
// 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1}
// $$
//
// Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit.
uint256 xAux = uint256(x);
result = 1;
if (xAux >= 2 ** 128) {
xAux >>= 128;
result <<= 64;
}
if (xAux >= 2 ** 64) {
xAux >>= 64;
result <<= 32;
}
if (xAux >= 2 ** 32) {
xAux >>= 32;
result <<= 16;
}
if (xAux >= 2 ** 16) {
xAux >>= 16;
result <<= 8;
}
if (xAux >= 2 ** 8) {
xAux >>= 8;
result <<= 4;
}
if (xAux >= 2 ** 4) {
xAux >>= 4;
result <<= 2;
}
if (xAux >= 2 ** 2) {
result <<= 1;
}
// At this point, `result` is an estimation with at least one bit of precision. We know the true value has at
// most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision
// doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of
// precision into the expected uint128 result.
unchecked {
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
// If x is not a perfect square, round the result toward zero.
uint256 roundedResult = x / result;
if (result >= roundedResult) {
result = roundedResult;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { SD1x18 } from "./ValueType.sol";
/// @dev Euler's number as an SD1x18 number.
SD1x18 constant E = SD1x18.wrap(2_718281828459045235);
/// @dev The maximum value an SD1x18 number can have.
int64 constant uMAX_SD1x18 = 9_223372036854775807;
SD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18);
/// @dev The maximum value an SD1x18 number can have.
int64 constant uMIN_SD1x18 = -9_223372036854775808;
SD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18);
/// @dev PI as an SD1x18 number.
SD1x18 constant PI = SD1x18.wrap(3_141592653589793238);
/// @dev The unit number, which gives the decimal precision of SD1x18.
SD1x18 constant UNIT = SD1x18.wrap(1e18);
int256 constant uUNIT = 1e18;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./Casting.sol" as Casting;
/// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18
/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity
/// type int64. This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract
/// storage.
type SD1x18 is int64;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using {
Casting.intoSD59x18,
Casting.intoUD2x18,
Casting.intoUD60x18,
Casting.intoUint256,
Casting.intoUint128,
Casting.intoUint40,
Casting.unwrap
} for SD1x18 global;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { UD2x18 } from "./ValueType.sol";
/// @dev Euler's number as a UD2x18 number.
UD2x18 constant E = UD2x18.wrap(2_718281828459045235);
/// @dev The maximum value a UD2x18 number can have.
uint64 constant uMAX_UD2x18 = 18_446744073709551615;
UD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18);
/// @dev PI as a UD2x18 number.
UD2x18 constant PI = UD2x18.wrap(3_141592653589793238);
/// @dev The unit number, which gives the decimal precision of UD2x18.
uint256 constant uUNIT = 1e18;
UD2x18 constant UNIT = UD2x18.wrap(1e18);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./Casting.sol" as Casting;
/// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18
/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity
/// type uint64. This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract
/// storage.
type UD2x18 is uint64;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using {
Casting.intoSD1x18,
Casting.intoSD59x18,
Casting.intoUD60x18,
Casting.intoUint256,
Casting.intoUint128,
Casting.intoUint40,
Casting.unwrap
} for UD2x18 global;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./Casting.sol" as Casting;
import "./Helpers.sol" as Helpers;
import "./Math.sol" as Math;
/// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18
/// decimals. The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256.
/// @dev The value type is defined here so it can be imported in all other files.
type UD60x18 is uint256;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using {
Casting.intoSD1x18,
Casting.intoUD2x18,
Casting.intoSD59x18,
Casting.intoUint128,
Casting.intoUint256,
Casting.intoUint40,
Casting.unwrap
} for UD60x18 global;
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
// The global "using for" directive makes the functions in this library callable on the UD60x18 type.
using {
Math.avg,
Math.ceil,
Math.div,
Math.exp,
Math.exp2,
Math.floor,
Math.frac,
Math.gm,
Math.inv,
Math.ln,
Math.log10,
Math.log2,
Math.mul,
Math.pow,
Math.powu,
Math.sqrt
} for UD60x18 global;
/*//////////////////////////////////////////////////////////////////////////
HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
// The global "using for" directive makes the functions in this library callable on the UD60x18 type.
using {
Helpers.add,
Helpers.and,
Helpers.eq,
Helpers.gt,
Helpers.gte,
Helpers.isZero,
Helpers.lshift,
Helpers.lt,
Helpers.lte,
Helpers.mod,
Helpers.neq,
Helpers.not,
Helpers.or,
Helpers.rshift,
Helpers.sub,
Helpers.uncheckedAdd,
Helpers.uncheckedSub,
Helpers.xor
} for UD60x18 global;
/*//////////////////////////////////////////////////////////////////////////
OPERATORS
//////////////////////////////////////////////////////////////////////////*/
// The global "using for" directive makes it possible to use these operators on the UD60x18 type.
using {
Helpers.add as +,
Helpers.and2 as &,
Math.div as /,
Helpers.eq as ==,
Helpers.gt as >,
Helpers.gte as >=,
Helpers.lt as <,
Helpers.lte as <=,
Helpers.or as |,
Helpers.mod as %,
Math.mul as *,
Helpers.neq as !=,
Helpers.not as ~,
Helpers.sub as -,
Helpers.xor as ^
} for UD60x18 global;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "../Common.sol" as Common;
import "./Errors.sol" as CastingErrors;
import { SD59x18 } from "../sd59x18/ValueType.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "../ud60x18/ValueType.sol";
import { SD1x18 } from "./ValueType.sol";
/// @notice Casts an SD1x18 number into SD59x18.
/// @dev There is no overflow check because the domain of SD1x18 is a subset of SD59x18.
function intoSD59x18(SD1x18 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(int256(SD1x18.unwrap(x)));
}
/// @notice Casts an SD1x18 number into UD2x18.
/// - x must be positive.
function intoUD2x18(SD1x18 x) pure returns (UD2x18 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD1x18_ToUD2x18_Underflow(x);
}
result = UD2x18.wrap(uint64(xInt));
}
/// @notice Casts an SD1x18 number into UD60x18.
/// @dev Requirements:
/// - x must be positive.
function intoUD60x18(SD1x18 x) pure returns (UD60x18 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD1x18_ToUD60x18_Underflow(x);
}
result = UD60x18.wrap(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint256.
/// @dev Requirements:
/// - x must be positive.
function intoUint256(SD1x18 x) pure returns (uint256 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD1x18_ToUint256_Underflow(x);
}
result = uint256(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint128.
/// @dev Requirements:
/// - x must be positive.
function intoUint128(SD1x18 x) pure returns (uint128 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD1x18_ToUint128_Underflow(x);
}
result = uint128(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint40.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(SD1x18 x) pure returns (uint40 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD1x18_ToUint40_Underflow(x);
}
if (xInt > int64(uint64(Common.MAX_UINT40))) {
revert CastingErrors.PRBMath_SD1x18_ToUint40_Overflow(x);
}
result = uint40(uint64(xInt));
}
/// @notice Alias for {wrap}.
function sd1x18(int64 x) pure returns (SD1x18 result) {
result = SD1x18.wrap(x);
}
/// @notice Unwraps an SD1x18 number into int64.
function unwrap(SD1x18 x) pure returns (int64 result) {
result = SD1x18.unwrap(x);
}
/// @notice Wraps an int64 number into SD1x18.
function wrap(int64 x) pure returns (SD1x18 result) {
result = SD1x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "../Common.sol" as Common;
import "./Errors.sol" as Errors;
import { uMAX_SD1x18 } from "../sd1x18/Constants.sol";
import { SD1x18 } from "../sd1x18/ValueType.sol";
import { SD59x18 } from "../sd59x18/ValueType.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "../ud60x18/ValueType.sol";
import { UD2x18 } from "./ValueType.sol";
/// @notice Casts a UD2x18 number into SD1x18.
/// - x must be less than or equal to `uMAX_SD1x18`.
function intoSD1x18(UD2x18 x) pure returns (SD1x18 result) {
uint64 xUint = UD2x18.unwrap(x);
if (xUint > uint64(uMAX_SD1x18)) {
revert Errors.PRBMath_UD2x18_IntoSD1x18_Overflow(x);
}
result = SD1x18.wrap(int64(xUint));
}
/// @notice Casts a UD2x18 number into SD59x18.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of SD59x18.
function intoSD59x18(UD2x18 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x))));
}
/// @notice Casts a UD2x18 number into UD60x18.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of UD60x18.
function intoUD60x18(UD2x18 x) pure returns (UD60x18 result) {
result = UD60x18.wrap(UD2x18.unwrap(x));
}
/// @notice Casts a UD2x18 number into uint128.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of uint128.
function intoUint128(UD2x18 x) pure returns (uint128 result) {
result = uint128(UD2x18.unwrap(x));
}
/// @notice Casts a UD2x18 number into uint256.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of uint256.
function intoUint256(UD2x18 x) pure returns (uint256 result) {
result = uint256(UD2x18.unwrap(x));
}
/// @notice Casts a UD2x18 number into uint40.
/// @dev Requirements:
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(UD2x18 x) pure returns (uint40 result) {
uint64 xUint = UD2x18.unwrap(x);
if (xUint > uint64(Common.MAX_UINT40)) {
revert Errors.PRBMath_UD2x18_IntoUint40_Overflow(x);
}
result = uint40(xUint);
}
/// @notice Alias for {wrap}.
function ud2x18(uint64 x) pure returns (UD2x18 result) {
result = UD2x18.wrap(x);
}
/// @notice Unwrap a UD2x18 number into uint64.
function unwrap(UD2x18 x) pure returns (uint64 result) {
result = UD2x18.unwrap(x);
}
/// @notice Wraps a uint64 number into UD2x18.
function wrap(uint64 x) pure returns (UD2x18 result) {
result = UD2x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./Errors.sol" as CastingErrors;
import { MAX_UINT128, MAX_UINT40 } from "../Common.sol";
import { uMAX_SD1x18 } from "../sd1x18/Constants.sol";
import { SD1x18 } from "../sd1x18/ValueType.sol";
import { uMAX_SD59x18 } from "../sd59x18/Constants.sol";
import { SD59x18 } from "../sd59x18/ValueType.sol";
import { uMAX_UD2x18 } from "../ud2x18/Constants.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "./ValueType.sol";
/// @notice Casts a UD60x18 number into SD1x18.
/// @dev Requirements:
/// - x must be less than or equal to `uMAX_SD1x18`.
function intoSD1x18(UD60x18 x) pure returns (SD1x18 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > uint256(int256(uMAX_SD1x18))) {
revert CastingErrors.PRBMath_UD60x18_IntoSD1x18_Overflow(x);
}
result = SD1x18.wrap(int64(uint64(xUint)));
}
/// @notice Casts a UD60x18 number into UD2x18.
/// @dev Requirements:
/// - x must be less than or equal to `uMAX_UD2x18`.
function intoUD2x18(UD60x18 x) pure returns (UD2x18 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > uMAX_UD2x18) {
revert CastingErrors.PRBMath_UD60x18_IntoUD2x18_Overflow(x);
}
result = UD2x18.wrap(uint64(xUint));
}
/// @notice Casts a UD60x18 number into SD59x18.
/// @dev Requirements:
/// - x must be less than or equal to `uMAX_SD59x18`.
function intoSD59x18(UD60x18 x) pure returns (SD59x18 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > uint256(uMAX_SD59x18)) {
revert CastingErrors.PRBMath_UD60x18_IntoSD59x18_Overflow(x);
}
result = SD59x18.wrap(int256(xUint));
}
/// @notice Casts a UD60x18 number into uint128.
/// @dev This is basically an alias for {unwrap}.
function intoUint256(UD60x18 x) pure returns (uint256 result) {
result = UD60x18.unwrap(x);
}
/// @notice Casts a UD60x18 number into uint128.
/// @dev Requirements:
/// - x must be less than or equal to `MAX_UINT128`.
function intoUint128(UD60x18 x) pure returns (uint128 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > MAX_UINT128) {
revert CastingErrors.PRBMath_UD60x18_IntoUint128_Overflow(x);
}
result = uint128(xUint);
}
/// @notice Casts a UD60x18 number into uint40.
/// @dev Requirements:
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(UD60x18 x) pure returns (uint40 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > MAX_UINT40) {
revert CastingErrors.PRBMath_UD60x18_IntoUint40_Overflow(x);
}
result = uint40(xUint);
}
/// @notice Alias for {wrap}.
function ud(uint256 x) pure returns (UD60x18 result) {
result = UD60x18.wrap(x);
}
/// @notice Alias for {wrap}.
function ud60x18(uint256 x) pure returns (UD60x18 result) {
result = UD60x18.wrap(x);
}
/// @notice Unwraps a UD60x18 number into uint256.
function unwrap(UD60x18 x) pure returns (uint256 result) {
result = UD60x18.unwrap(x);
}
/// @notice Wraps a uint256 number into the UD60x18 value type.
function wrap(uint256 x) pure returns (UD60x18 result) {
result = UD60x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { wrap } from "./Casting.sol";
import { UD60x18 } from "./ValueType.sol";
/// @notice Implements the checked addition operation (+) in the UD60x18 type.
function add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(x.unwrap() + y.unwrap());
}
/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.
function and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {
result = wrap(x.unwrap() & bits);
}
/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.
function and2(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(x.unwrap() & y.unwrap());
}
/// @notice Implements the equal operation (==) in the UD60x18 type.
function eq(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = x.unwrap() == y.unwrap();
}
/// @notice Implements the greater than operation (>) in the UD60x18 type.
function gt(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = x.unwrap() > y.unwrap();
}
/// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type.
function gte(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = x.unwrap() >= y.unwrap();
}
/// @notice Implements a zero comparison check function in the UD60x18 type.
function isZero(UD60x18 x) pure returns (bool result) {
// This wouldn't work if x could be negative.
result = x.unwrap() == 0;
}
/// @notice Implements the left shift operation (<<) in the UD60x18 type.
function lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {
result = wrap(x.unwrap() << bits);
}
/// @notice Implements the lower than operation (<) in the UD60x18 type.
function lt(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = x.unwrap() < y.unwrap();
}
/// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type.
function lte(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = x.unwrap() <= y.unwrap();
}
/// @notice Implements the checked modulo operation (%) in the UD60x18 type.
function mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(x.unwrap() % y.unwrap());
}
/// @notice Implements the not equal operation (!=) in the UD60x18 type.
function neq(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = x.unwrap() != y.unwrap();
}
/// @notice Implements the NOT (~) bitwise operation in the UD60x18 type.
function not(UD60x18 x) pure returns (UD60x18 result) {
result = wrap(~x.unwrap());
}
/// @notice Implements the OR (|) bitwise operation in the UD60x18 type.
function or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(x.unwrap() | y.unwrap());
}
/// @notice Implements the right shift operation (>>) in the UD60x18 type.
function rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {
result = wrap(x.unwrap() >> bits);
}
/// @notice Implements the checked subtraction operation (-) in the UD60x18 type.
function sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(x.unwrap() - y.unwrap());
}
/// @notice Implements the unchecked addition operation (+) in the UD60x18 type.
function uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
unchecked {
result = wrap(x.unwrap() + y.unwrap());
}
}
/// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type.
function uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
unchecked {
result = wrap(x.unwrap() - y.unwrap());
}
}
/// @notice Implements the XOR (^) bitwise operation in the UD60x18 type.
function xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(x.unwrap() ^ y.unwrap());
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "../Common.sol" as Common;
import "./Errors.sol" as Errors;
import { wrap } from "./Casting.sol";
import {
uEXP_MAX_INPUT,
uEXP2_MAX_INPUT,
uHALF_UNIT,
uLOG2_10,
uLOG2_E,
uMAX_UD60x18,
uMAX_WHOLE_UD60x18,
UNIT,
uUNIT,
uUNIT_SQUARED,
ZERO
} from "./Constants.sol";
import { UD60x18 } from "./ValueType.sol";
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/// @notice Calculates the arithmetic average of x and y using the following formula:
///
/// $$
/// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2)
/// $$
//
/// In English, this is what this formula does:
///
/// 1. AND x and y.
/// 2. Calculate half of XOR x and y.
/// 3. Add the two results together.
///
/// This technique is known as SWAR, which stands for "SIMD within a register". You can read more about it here:
/// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223
///
/// @dev Notes:
/// - The result is rounded toward zero.
///
/// @param x The first operand as a UD60x18 number.
/// @param y The second operand as a UD60x18 number.
/// @return result The arithmetic average as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
uint256 yUint = y.unwrap();
unchecked {
result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1));
}
}
/// @notice Yields the smallest whole number greater than or equal to x.
///
/// @dev This is optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional
/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be less than or equal to `MAX_WHOLE_UD60x18`.
///
/// @param x The UD60x18 number to ceil.
/// @param result The smallest whole number greater than or equal to x, as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function ceil(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
if (xUint > uMAX_WHOLE_UD60x18) {
revert Errors.PRBMath_UD60x18_Ceil_Overflow(x);
}
assembly ("memory-safe") {
// Equivalent to `x % UNIT`.
let remainder := mod(x, uUNIT)
// Equivalent to `UNIT - remainder`.
let delta := sub(uUNIT, remainder)
// Equivalent to `x + remainder > 0 ? delta : 0`.
result := add(x, mul(delta, gt(remainder, 0)))
}
}
/// @notice Divides two UD60x18 numbers, returning a new UD60x18 number.
///
/// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division.
///
/// Notes:
/// - Refer to the notes in {Common.mulDiv}.
///
/// Requirements:
/// - Refer to the requirements in {Common.mulDiv}.
///
/// @param x The numerator as a UD60x18 number.
/// @param y The denominator as a UD60x18 number.
/// @param result The quotient as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(Common.mulDiv(x.unwrap(), uUNIT, y.unwrap()));
}
/// @notice Calculates the natural exponent of x using the following formula:
///
/// $$
/// e^x = 2^{x * log_2{e}}
/// $$
///
/// @dev Requirements:
/// - x must be less than 133_084258667509499441.
///
/// @param x The exponent as a UD60x18 number.
/// @return result The result as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function exp(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
// This check prevents values greater than 192e18 from being passed to {exp2}.
if (xUint > uEXP_MAX_INPUT) {
revert Errors.PRBMath_UD60x18_Exp_InputTooBig(x);
}
unchecked {
// Inline the fixed-point multiplication to save gas.
uint256 doubleUnitProduct = xUint * uLOG2_E;
result = exp2(wrap(doubleUnitProduct / uUNIT));
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method.
///
/// @dev See https://ethereum.stackexchange.com/q/79903/24693
///
/// Requirements:
/// - x must be less than 192e18.
/// - The result must fit in UD60x18.
///
/// @param x The exponent as a UD60x18 number.
/// @return result The result as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function exp2(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
// Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.
if (xUint > uEXP2_MAX_INPUT) {
revert Errors.PRBMath_UD60x18_Exp2_InputTooBig(x);
}
// Convert x to the 192.64-bit fixed-point format.
uint256 x_192x64 = (xUint << 64) / uUNIT;
// Pass x to the {Common.exp2} function, which uses the 192.64-bit fixed-point number representation.
result = wrap(Common.exp2(x_192x64));
}
/// @notice Yields the greatest whole number less than or equal to x.
/// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
/// @param x The UD60x18 number to floor.
/// @param result The greatest whole number less than or equal to x, as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function floor(UD60x18 x) pure returns (UD60x18 result) {
assembly ("memory-safe") {
// Equivalent to `x % UNIT`.
let remainder := mod(x, uUNIT)
// Equivalent to `x - remainder > 0 ? remainder : 0)`.
result := sub(x, mul(remainder, gt(remainder, 0)))
}
}
/// @notice Yields the excess beyond the floor of x using the odd function definition.
/// @dev See https://en.wikipedia.org/wiki/Fractional_part.
/// @param x The UD60x18 number to get the fractional part of.
/// @param result The fractional part of x as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function frac(UD60x18 x) pure returns (UD60x18 result) {
assembly ("memory-safe") {
result := mod(x, uUNIT)
}
}
/// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$, rounding down.
///
/// @dev Requirements:
/// - x * y must fit in UD60x18.
///
/// @param x The first operand as a UD60x18 number.
/// @param y The second operand as a UD60x18 number.
/// @return result The result as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
uint256 yUint = y.unwrap();
if (xUint == 0 || yUint == 0) {
return ZERO;
}
unchecked {
// Checking for overflow this way is faster than letting Solidity do it.
uint256 xyUint = xUint * yUint;
if (xyUint / xUint != yUint) {
revert Errors.PRBMath_UD60x18_Gm_Overflow(x, y);
}
// We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`
// during multiplication. See the comments in {Common.sqrt}.
result = wrap(Common.sqrt(xyUint));
}
}
/// @notice Calculates the inverse of x.
///
/// @dev Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - x must not be zero.
///
/// @param x The UD60x18 number for which to calculate the inverse.
/// @return result The inverse as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function inv(UD60x18 x) pure returns (UD60x18 result) {
unchecked {
result = wrap(uUNIT_SQUARED / x.unwrap());
}
}
/// @notice Calculates the natural logarithm of x using the following formula:
///
/// $$
/// ln{x} = log_2{x} / log_2{e}
/// $$
///
/// @dev Notes:
/// - Refer to the notes in {log2}.
/// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.
///
/// Requirements:
/// - Refer to the requirements in {log2}.
///
/// @param x The UD60x18 number for which to calculate the natural logarithm.
/// @return result The natural logarithm as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function ln(UD60x18 x) pure returns (UD60x18 result) {
unchecked {
// Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that
// {log2} can return is ~196_205294292027477728.
result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);
}
}
/// @notice Calculates the common logarithm of x using the following formula:
///
/// $$
/// log_{10}{x} = log_2{x} / log_2{10}
/// $$
///
/// However, if x is an exact power of ten, a hard coded value is returned.
///
/// @dev Notes:
/// - Refer to the notes in {log2}.
///
/// Requirements:
/// - Refer to the requirements in {log2}.
///
/// @param x The UD60x18 number for which to calculate the common logarithm.
/// @return result The common logarithm as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function log10(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
if (xUint < uUNIT) {
revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x);
}
// Note that the `mul` in this assembly block is the standard multiplication operation, not {UD60x18.mul}.
// prettier-ignore
assembly ("memory-safe") {
switch x
case 1 { result := mul(uUNIT, sub(0, 18)) }
case 10 { result := mul(uUNIT, sub(1, 18)) }
case 100 { result := mul(uUNIT, sub(2, 18)) }
case 1000 { result := mul(uUNIT, sub(3, 18)) }
case 10000 { result := mul(uUNIT, sub(4, 18)) }
case 100000 { result := mul(uUNIT, sub(5, 18)) }
case 1000000 { result := mul(uUNIT, sub(6, 18)) }
case 10000000 { result := mul(uUNIT, sub(7, 18)) }
case 100000000 { result := mul(uUNIT, sub(8, 18)) }
case 1000000000 { result := mul(uUNIT, sub(9, 18)) }
case 10000000000 { result := mul(uUNIT, sub(10, 18)) }
case 100000000000 { result := mul(uUNIT, sub(11, 18)) }
case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }
case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }
case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }
case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }
case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }
case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := uUNIT }
case 100000000000000000000 { result := mul(uUNIT, 2) }
case 1000000000000000000000 { result := mul(uUNIT, 3) }
case 10000000000000000000000 { result := mul(uUNIT, 4) }
case 100000000000000000000000 { result := mul(uUNIT, 5) }
case 1000000000000000000000000 { result := mul(uUNIT, 6) }
case 10000000000000000000000000 { result := mul(uUNIT, 7) }
case 100000000000000000000000000 { result := mul(uUNIT, 8) }
case 1000000000000000000000000000 { result := mul(uUNIT, 9) }
case 10000000000000000000000000000 { result := mul(uUNIT, 10) }
case 100000000000000000000000000000 { result := mul(uUNIT, 11) }
case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }
case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }
case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }
case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }
case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }
case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }
case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }
case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }
case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }
case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }
case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }
case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) }
default { result := uMAX_UD60x18 }
}
if (result.unwrap() == uMAX_UD60x18) {
unchecked {
// Inline the fixed-point division to save gas.
result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);
}
}
}
/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:
///
/// $$
/// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2)
/// $$
///
/// For $0 \leq x \lt 1$, the input is inverted:
///
/// $$
/// log_2{x} = -log_2{\frac{1}{x}}
/// $$
///
/// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
///
/// Notes:
/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.
///
/// Requirements:
/// - x must be greater than zero.
///
/// @param x The UD60x18 number for which to calculate the binary logarithm.
/// @return result The binary logarithm as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function log2(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
if (xUint < uUNIT) {
revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x);
}
unchecked {
// Calculate the integer part of the logarithm.
uint256 n = Common.msb(xUint / uUNIT);
// This is the integer part of the logarithm as a UD60x18 number. The operation can't overflow because n
// n is at most 255 and UNIT is 1e18.
uint256 resultUint = n * uUNIT;
// Calculate $y = x * 2^{-n}$.
uint256 y = xUint >> n;
// If y is the unit number, the fractional part is zero.
if (y == uUNIT) {
return wrap(resultUint);
}
// Calculate the fractional part via the iterative approximation.
// The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.
uint256 DOUBLE_UNIT = 2e18;
for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {
y = (y * y) / uUNIT;
// Is y^2 >= 2e18 and so in the range [2e18, 4e18)?
if (y >= DOUBLE_UNIT) {
// Add the 2^{-m} factor to the logarithm.
resultUint += delta;
// Halve y, which corresponds to z/2 in the Wikipedia article.
y >>= 1;
}
}
result = wrap(resultUint);
}
}
/// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number.
///
/// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division.
///
/// Notes:
/// - Refer to the notes in {Common.mulDiv}.
///
/// Requirements:
/// - Refer to the requirements in {Common.mulDiv}.
///
/// @dev See the documentation in {Common.mulDiv18}.
/// @param x The multiplicand as a UD60x18 number.
/// @param y The multiplier as a UD60x18 number.
/// @return result The product as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(Common.mulDiv18(x.unwrap(), y.unwrap()));
}
/// @notice Raises x to the power of y.
///
/// For $1 \leq x \leq \infty$, the following standard formula is used:
///
/// $$
/// x^y = 2^{log_2{x} * y}
/// $$
///
/// For $0 \leq x \lt 1$, since the unsigned {log2} is undefined, an equivalent formula is used:
///
/// $$
/// i = \frac{1}{x}
/// w = 2^{log_2{i} * y}
/// x^y = \frac{1}{w}
/// $$
///
/// @dev Notes:
/// - Refer to the notes in {log2} and {mul}.
/// - Returns `UNIT` for 0^0.
/// - It may not perform well with very small values of x. Consider using SD59x18 as an alternative.
///
/// Requirements:
/// - Refer to the requirements in {exp2}, {log2}, and {mul}.
///
/// @param x The base as a UD60x18 number.
/// @param y The exponent as a UD60x18 number.
/// @return result The result as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
uint256 yUint = y.unwrap();
// If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.
if (xUint == 0) {
return yUint == 0 ? UNIT : ZERO;
}
// If x is `UNIT`, the result is always `UNIT`.
else if (xUint == uUNIT) {
return UNIT;
}
// If y is zero, the result is always `UNIT`.
if (yUint == 0) {
return UNIT;
}
// If y is `UNIT`, the result is always x.
else if (yUint == uUNIT) {
return x;
}
// If x is greater than `UNIT`, use the standard formula.
if (xUint > uUNIT) {
result = exp2(mul(log2(x), y));
}
// Conversely, if x is less than `UNIT`, use the equivalent formula.
else {
UD60x18 i = wrap(uUNIT_SQUARED / xUint);
UD60x18 w = exp2(mul(log2(i), y));
result = wrap(uUNIT_SQUARED / w.unwrap());
}
}
/// @notice Raises x (a UD60x18 number) to the power y (an unsigned basic integer) using the well-known
/// algorithm "exponentiation by squaring".
///
/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.
///
/// Notes:
/// - Refer to the notes in {Common.mulDiv18}.
/// - Returns `UNIT` for 0^0.
///
/// Requirements:
/// - The result must fit in UD60x18.
///
/// @param x The base as a UD60x18 number.
/// @param y The exponent as a uint256.
/// @return result The result as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) {
// Calculate the first iteration of the loop in advance.
uint256 xUint = x.unwrap();
uint256 resultUint = y & 1 > 0 ? xUint : uUNIT;
// Equivalent to `for(y /= 2; y > 0; y /= 2)`.
for (y >>= 1; y > 0; y >>= 1) {
xUint = Common.mulDiv18(xUint, xUint);
// Equivalent to `y % 2 == 1`.
if (y & 1 > 0) {
resultUint = Common.mulDiv18(resultUint, xUint);
}
}
result = wrap(resultUint);
}
/// @notice Calculates the square root of x using the Babylonian method.
///
/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - x must be less than `MAX_UD60x18 / UNIT`.
///
/// @param x The UD60x18 number for which to calculate the square root.
/// @return result The result as a UD60x18 number.
/// @custom:smtchecker abstract-function-nondet
function sqrt(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = x.unwrap();
unchecked {
if (xUint > uMAX_UD60x18 / uUNIT) {
revert Errors.PRBMath_UD60x18_Sqrt_Overflow(x);
}
// Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two UD60x18 numbers.
// In this case, the two numbers are both the square root.
result = wrap(Common.sqrt(xUint * uUNIT));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { SD1x18 } from "./ValueType.sol";
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD2x18.
error PRBMath_SD1x18_ToUD2x18_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD60x18.
error PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint128.
error PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint256.
error PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40.
error PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40.
error PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { UD2x18 } from "./ValueType.sol";
/// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in SD1x18.
error PRBMath_UD2x18_IntoSD1x18_Overflow(UD2x18 x);
/// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in uint40.
error PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { UD60x18 } from "./ValueType.sol";
/// @notice Thrown when ceiling a number overflows UD60x18.
error PRBMath_UD60x18_Ceil_Overflow(UD60x18 x);
/// @notice Thrown when converting a basic integer to the fixed-point format overflows UD60x18.
error PRBMath_UD60x18_Convert_Overflow(uint256 x);
/// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441.
error PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x);
/// @notice Thrown when taking the binary exponent of a base greater than 192e18.
error PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x);
/// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows UD60x18.
error PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.
error PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD59x18.
error PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.
error PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.
error PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x);
/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.
error PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x);
/// @notice Thrown when taking the logarithm of a number less than 1.
error PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x);
/// @notice Thrown when calculating the square root overflows UD60x18.
error PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { UD60x18 } from "./ValueType.sol";
// NOTICE: the "u" prefix stands for "unwrapped".
/// @dev Euler's number as a UD60x18 number.
UD60x18 constant E = UD60x18.wrap(2_718281828459045235);
/// @dev The maximum input permitted in {exp}.
uint256 constant uEXP_MAX_INPUT = 133_084258667509499440;
UD60x18 constant EXP_MAX_INPUT = UD60x18.wrap(uEXP_MAX_INPUT);
/// @dev The maximum input permitted in {exp2}.
uint256 constant uEXP2_MAX_INPUT = 192e18 - 1;
UD60x18 constant EXP2_MAX_INPUT = UD60x18.wrap(uEXP2_MAX_INPUT);
/// @dev Half the UNIT number.
uint256 constant uHALF_UNIT = 0.5e18;
UD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT);
/// @dev $log_2(10)$ as a UD60x18 number.
uint256 constant uLOG2_10 = 3_321928094887362347;
UD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10);
/// @dev $log_2(e)$ as a UD60x18 number.
uint256 constant uLOG2_E = 1_442695040888963407;
UD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E);
/// @dev The maximum value a UD60x18 number can have.
uint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935;
UD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18);
/// @dev The maximum whole value a UD60x18 number can have.
uint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000;
UD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18);
/// @dev PI as a UD60x18 number.
UD60x18 constant PI = UD60x18.wrap(3_141592653589793238);
/// @dev The unit number, which gives the decimal precision of UD60x18.
uint256 constant uUNIT = 1e18;
UD60x18 constant UNIT = UD60x18.wrap(uUNIT);
/// @dev The unit number squared.
uint256 constant uUNIT_SQUARED = 1e36;
UD60x18 constant UNIT_SQUARED = UD60x18.wrap(uUNIT_SQUARED);
/// @dev Zero as a UD60x18 number.
UD60x18 constant ZERO = UD60x18.wrap(0);{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"aave-address-book/=lib/aave-address-book/src/",
"chainlink/=lib/pt-v5-chainlink-vrf-v2-direct/lib/chainlink/contracts/src/v0.8/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"prb-math/=lib/pt-v5-cgda-liquidator/lib/prb-math/src/",
"solidity-stringutils/=lib/solidity-stringutils/src/",
"yield-daddy/=lib/yield-daddy/src/",
"pt-v5-chainlink-vrf-v2-direct/=lib/pt-v5-chainlink-vrf-v2-direct/src/",
"pt-v5-draw-auction/=lib/pt-v5-draw-auction/src/",
"pt-v5-cgda-liquidator/=lib/pt-v5-cgda-liquidator/src/",
"pt-v5-liquidator-interfaces/=lib/pt-v5-cgda-liquidator/lib/pt-v5-liquidator-interfaces/src/interfaces/",
"pt-v5-prize-pool/=lib/pt-v5-prize-pool/src/",
"pt-v5-twab-controller/=lib/pt-v5-twab-controller/src/",
"pt-v5-vault/=lib/pt-v5-vault/src/",
"pt-v5-vault-boost/=lib/pt-v5-vault-boost/src/",
"pt-v5-vault-mock/=lib/pt-v5-vault/test/contracts/mock/",
"pt-v5-claimer/=lib/pt-v5-claimer/src/",
"rng/=lib/pt-v5-draw-auction/lib/pt-v5-rng-contracts/contracts/",
"rng-contracts/=lib/pt-v5-draw-auction/lib/pt-v5-rng-contracts/contracts/",
"remote-owner/=lib/pt-v5-draw-auction/lib/remote-owner/src/",
"@aave/core-v3/=lib/aave-address-book/lib/aave-v3-core/",
"@aave/periphery-v3/=lib/aave-address-book/lib/aave-v3-periphery/",
"@openzeppelin/=lib/pt-v5-draw-auction/lib/openzeppelin-contracts/",
"@prb/test/=lib/pt-v5-vault-boost/lib/prb-math/lib/prb-test/src/",
"aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/",
"aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/",
"brokentoken/=lib/pt-v5-vault/lib/brokentoken/src/",
"create3-factory/=lib/yield-daddy/lib/create3-factory/",
"erc4626-tests/=lib/pt-v5-vault/lib/erc4626-tests/",
"erc5164-interfaces/=lib/pt-v5-draw-auction/lib/remote-owner/lib/erc5164-interfaces/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"owner-manager-contracts/=lib/pt-v5-chainlink-vrf-v2-direct/lib/owner-manager-contracts/contracts/",
"owner-manager/=lib/pt-v5-chainlink-vrf-v2-direct/lib/owner-manager-contracts/contracts/",
"prb-test/=lib/pt-v5-vault-boost/lib/prb-math/lib/prb-test/src/",
"pt-v5-rng-contracts/=lib/pt-v5-rng-contracts/contracts/",
"pt-v5-twab-delegator/=lib/pt-v5-twab-delegator/src/",
"ring-buffer-lib/=lib/pt-v5-twab-controller/lib/ring-buffer-lib/src/",
"rng/=lib/pt-v5-draw-auction/lib/pt-v5-rng-contracts/contracts/",
"solmate/=lib/yield-daddy/lib/solmate/src/",
"uniform-random-number/=lib/pt-v5-prize-pool/lib/uniform-random-number/src/",
"weird-erc20/=lib/pt-v5-vault/lib/brokentoken/lib/weird-erc20/src/"
],
"optimizer": {
"enabled": true,
"runs": 200,
"details": {
"peephole": true,
"inliner": true,
"deduplicate": true,
"cse": true,
"yul": true
}
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract LiquidationPair","name":"pair","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"contract ILiquidationSource","name":"source","type":"address"},{"indexed":false,"internalType":"uint32","name":"periodLength","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"firstPeriodStartsAt","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"targetFirstSaleTime","type":"uint32"},{"indexed":false,"internalType":"SD59x18","name":"decayConstant","type":"int256"},{"indexed":false,"internalType":"uint104","name":"initialAmountIn","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"initialAmountOut","type":"uint104"},{"indexed":false,"internalType":"uint256","name":"minimumAuctionAmount","type":"uint256"}],"name":"PairCreated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"contract LiquidationPair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILiquidationSource","name":"_source","type":"address"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint32","name":"_periodLength","type":"uint32"},{"internalType":"uint32","name":"_firstPeriodStartsAt","type":"uint32"},{"internalType":"uint32","name":"_targetFirstSaleTime","type":"uint32"},{"internalType":"SD59x18","name":"_decayConstant","type":"int256"},{"internalType":"uint104","name":"_initialAmountIn","type":"uint104"},{"internalType":"uint104","name":"_initialAmountOut","type":"uint104"},{"internalType":"uint256","name":"_minimumAuctionAmount","type":"uint256"}],"name":"createPair","outputs":[{"internalType":"contract LiquidationPair","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract LiquidationPair","name":"","type":"address"}],"name":"deployedPairs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPairs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60808060405234610016576139c9908161001c8239f35b600080fdfe604060808152600490813610156200001657600080fd5b600090813560e01c80631e3dd18b14620002c45780635d8c32a914620002a65780639cded5ab14620002645763f228d46b146200005257600080fd5b346200026057610140918260031936011262000255576001600160a01b03928435848116908190036200025c5760243591858316809303620002585760443593868516809503620002555760643563ffffffff8082168092036200025c57608435818116809103620002585760a435918216809203620002585760e435926cffffffffffffffffffffffffff9485851680950362000255576101043595861680960362000255578a51610124359761363f8083019067ffffffffffffffff8211848310176200024057908d8f8e8e8795620003558739845260208401528201528560608201528660808201528760a082015260c43560c08201528860e0820152896101008201528a61012082015203019082f08015620002345781546801000000000000000081101562000221578d9e50908160018e9f9c9d9e94930183556200019c9062000309565b9b9091169e8f9b82549060031b918d831b921b191617905589815260016020522060ff1981541660011790558a51968752602087015289860152606085015260c435608085015260a084015260c083015260e08201526101007f955594a69091ec47a9c770953195b25368e20e0c19791ccc001cdfdd6076555791a451908152602090f35b634e487b7160e01b835260418f52602483fd5b508a51903d90823e3d90fd5b508f846041602492634e487b7160e01b835252fd5b80fd5b8380fd5b8280fd5b5080fd5b5082346200025c5760203660031901126200025c57356001600160a01b038116908190036200025c57818360ff92602095526001855220541690519015158152f35b50346200026057816003193601126200026057602091549051908152f35b5082346200025c5760203660031901126200025c5735918054831015620002555750620002f360209262000309565b905491519160018060a01b039160031b1c168152f35b90600091825481101562000340578280527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563019190565b634e487b7160e01b83526032600452602483fdfe610180604081815234620003ae5781906200363f8038038091620000248286620003b3565b843961014092839181010312620003ae578251916001600160a01b038084169290838503620003ae5785946200005d60208701620003ed565b6200006a848801620003ed565b90620000796060890162000402565b916200008860808a0162000402565b926200009760a08b0162000402565b9160c08b015193620000ac60e08d0162000414565b96620000bd6101009e8f0162000414565b98610120809e01519c156200039d57808316156200038c578316156200037b5760805260a05260c05260e083905263ffffffff908116808c529381168a529087529162000115906200010f9062000429565b62000491565b90680736ea4425c11ac630806200012d848462000679565b13620002b557505050845116875180821015620002985750506001600160681b0390811690811562000287578216156200027657600080546001600160d01b0319169190911760689290921b600160681b600160d01b03169190911790556101609283526200019b620007c1565b519261211494856200152b8639608051858181610176015281816104a6015281816107b701528181611019015261145c015260a05185818161014401528181610462015261086a015260c051858181610259015281816107f201528181610fe80152611427015260e05185818161052e0152818161124d015261157201525184818161021d01528181610347015281816105e2015281816113d1015261177a0152518381816102a00152818161036f0152818161133a01526117450152518281816104f2015261150601525181818161042a01526114910152f35b825163427fe21b60e01b8152600490fd5b83516340561e0d60e01b8152600490fd5b6044925084519163a3f8209f60e01b835260048301526024820152fd5b869190600160ff1b84146200036a576000841215620003635783600003935b84156200034d576044946f641f188c35bc17242856994ebac0000004916001600160ff1b0383116200033257600091600019911813156200032a5750915b5191635357a16160e11b835260048301526024820152fd5b039162000312565b859185519163d49c26b360e01b835260048301526024820152fd5b634e487b7160e01b600052601260045260246000fd5b83620002d4565b82516309fe2b4560e41b8152600490fd5b895163104ccf9960e21b8152600490fd5b8a5163edf0381360e01b8152600490fd5b8a51637cee330760e11b8152600490fd5b600080fd5b601f909101601f19168101906001600160401b03821190821017620003d757604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620003ae57565b519063ffffffff82168203620003ae57565b51906001600160681b0382168203620003ae57565b6001600160ff1b0381116200043b5790565b60405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608490fd5b7809392ee8e921d5d073aff322e62439fcf32d7f344649470f8f198112620004f9577809392ee8e921d5d073aff322e62439fcf32d7f344649470f908113620004e157670de0b6b3a76400000290565b60249060405190639d58109160e01b82526004820152fd5b602490604051906399474eeb60e01b82526004820152fd5b90600160ff1b808314908115620005ba575b50620005a85760008212156200059d5762000551826000035b600083121562000595578260000390620005c5565b916001600160ff1b03831162000578576000916000199118131562000574575090565b0390565b6044916040519163d49c26b360e01b835260048301526024820152fd5b8290620005c5565b62000551826200053c565b6040516309fe2b4560e41b8152600490fd5b905081143862000523565b670de0b6b3a76400009160001983830992808302928380861095039480860395146200066a57828510156200064757908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b8260649260405192630c740aef60e31b8452600484015260248301526044820152fd5b5050809250156200034d570490565b90600160ff1b8083149081156200071e575b506200070c5760008212156200070157620006b9826000035b6000831215620006f957826000039062000729565b916001600160ff1b038311620006dc576000916000199118131562000574575090565b6044916040519163120b5b4360e01b835260048301526024820152fd5b829062000729565b620006b982620006a4565b60405163a6070c2560e01b8152600490fd5b90508114386200068b565b90919060001983820983820291828083109203918083039214620007b057670de0b6b3a764000090818310156200079257947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b6044908660405191635173648d60e01b835260048301526024820152fd5b5050670de0b6b3a764000090049150565b6101205180421062000ba057600154906001600160681b039081831660008115158062000b91575b1562000b7d5750600080546001600160d01b0319168217600160681b600160d01b03861617905560689390931c8216925b600080546001600160d01b031690556101008051156001171562000a1b5765ffffffffffff831162000b295760d09290921b6001600160d01b03191660015560805160c05160405163587e7b1360e11b81526001600160a01b039182166004820152602094929091859183916024918391600091165af190811562000b1d5760009162000ae7575b508061016051821060001462000ab7575050620008d0620008c86200010f600062000429565b915162000429565b8060030b90810362000a635790620008ec620008f39262000491565b9062000511565b600281905593841562000a3157620009186200010f63ffffffff610140511662000429565b9462000925818762000679565b94620009578662000951620009406200010f85891662000429565b620008ec6200010f86891662000429565b62000679565b946200098c6200097884620009866200097e6200097860e0519d8e62000679565b62000ba3565b9a8c62000679565b62000511565b96670de0b6b3a763ffff19880197881360011662000a1b57600098620009e660a098620009df7f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a039b620009ed9562000511565b9262000679565b9062000679565b6003555b60015460d01c916003549481604051971687521690850152604084015260608301526080820152a2565b634e487b7160e01b600052601160045260246000fd5b6000947f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a039460a09487600355620009f1565b60405162461bcd60e51b815260048101859052602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b620008d091620008c8916200010f916001600160c01b0390811062000ade575b5062000429565b90503862000ad7565b908482813d831162000b15575b62000b008183620003b3565b8101031262000b1257505138620008a2565b80fd5b503d62000af4565b6040513d6000823e3d90fd5b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b54606881901c84169450831690506200081a565b50838560681c161515620007e9565b50565b68023f3bfb6373f0ffff19811262000c0057680736ea4425c11ac630811362000be857670de0b6b3a76400006714057b7ef767814f62000be592020562000c21565b90565b6024906040519063ca7ec0c560e01b82526004820152fd5b50600090565b80156200034d576ec097ce7bc90715b34b9f10000000000590565b600081121562000c565768033dd1780914b9711419811262000c005762000c4b9060000362000c21565b62000be59062000c06565b680a688906bd8affffff81136200151357670de0b6b3a764000080604092831b0590600160bf1b67ff000000000000008316620013f2575b66ff0000000000008316620012da575b65ff00000000008316620011ca575b64ff000000008316620010c2575b63ff000000831662000fc2575b62ff0000831662000eca575b61ff00831662000dda575b60ff831662000cf3575b02911c60bf031c90565b6080831662000dc7575b83831662000db4575b6020831662000da1575b6010831662000d8e575b6008831662000d7b575b6004831662000d68575b6002831662000d55575b600183161562000ce9576801000000000000000102831c62000ce9565b6801000000000000000102831c62000d38565b6801000000000000000302831c62000d2e565b6801000000000000000602831c62000d24565b6801000000000000000b02831c62000d1a565b6801000000000000001602831c62000d10565b6801000000000000002c02831c62000d06565b6801000000000000005902831c62000cfd565b618000831662000eb7575b614000831662000ea4575b612000831662000e91575b611000831662000e7e575b610800831662000e6b575b610400831662000e58575b610200831662000e45575b61010083161562000cdf57680100000000000000b102831c62000cdf565b6801000000000000016302831c62000e27565b680100000000000002c602831c62000e1c565b6801000000000000058c02831c62000e11565b68010000000000000b1702831c62000e06565b6801000000000000162e02831c62000dfb565b68010000000000002c5d02831c62000df0565b680100000000000058b902831c62000de5565b62800000831662000faf575b62400000831662000f9c575b62200000831662000f89575b62100000831662000f76575b62080000831662000f63575b62040000831662000f50575b62020000831662000f3d575b6201000083161562000cd4576801000000000000b17202831c62000cd4565b680100000000000162e402831c62000f1e565b6801000000000002c5c802831c62000f12565b68010000000000058b9102831c62000f06565b680100000000000b172102831c62000efa565b68010000000000162e4302831c62000eee565b680100000000002c5c8602831c62000ee2565b6801000000000058b90c02831c62000ed6565b63800000008316620010af575b634000000083166200109c575b6320000000831662001089575b6310000000831662001076575b6308000000831662001063575b6304000000831662001050575b630200000083166200103d575b630100000083161562000cc85768010000000000b1721802831c62000cc8565b6801000000000162e43002831c6200101d565b68010000000002c5c86002831c62001010565b680100000000058b90c002831c62001003565b6801000000000b17217f02831c62000ff6565b680100000000162e42ff02831c62000fe9565b6801000000002c5c85fe02831c62000fdc565b68010000000058b90bfc02831c62000fcf565b6480000000008316620011b7575b6440000000008316620011a4575b642000000000831662001191575b64100000000083166200117e575b64080000000083166200116b575b640400000000831662001158575b640200000000831662001145575b64010000000083161562000cbb57680100000000b17217f802831c62000cbb565b68010000000162e42ff102831c62001124565b680100000002c5c85fe302831c62001116565b6801000000058b90bfce02831c62001108565b68010000000b17217fbb02831c620010fa565b6801000000162e42fff002831c620010ec565b68010000002c5c8601cc02831c620010de565b680100000058b90c0b4902831c620010d0565b658000000000008316620012c7575b654000000000008316620012b4575b652000000000008316620012a1575b6510000000000083166200128e575b6508000000000083166200127b575b65040000000000831662001268575b65020000000000831662001255575b6501000000000083161562000cad576801000000b17218355102831c62000cad565b680100000162e430e5a202831c62001233565b6801000002c5c863b73f02831c62001224565b68010000058b90cf1e6e02831c62001215565b680100000b1721bcfc9a02831c62001206565b68010000162e43f4f83102831c620011f7565b680100002c5c89d5ec6d02831c620011e8565b6801000058b91b5bc9ae02831c620011d9565b66800000000000008316620013df575b66400000000000008316620013cc575b66200000000000008316620013b9575b66100000000000008316620013a6575b6608000000000000831662001393575b6604000000000000831662001380575b660200000000000083166200136d575b660100000000000083161562000c9e5768010000b17255775c0402831c62000c9e565b6801000162e525ee054702831c6200134a565b68010002c5cc37da949202831c6200133a565b680100058ba01fb9f96d02831c6200132a565b6801000b175effdc76ba02831c6200131a565b680100162f3904051fa102831c6200130a565b6801002c605e2e8cec5002831c620012fa565b68010058c86da1c09ea202831c620012ea565b6780000000000000008316620014ff575b6740000000000000008316620014ec575b6720000000000000008316620014d9575b6710000000000000008316620014c6575b6708000000000000008316620014b3575b6704000000000000008316620014a0575b67020000000000000083166200148d575b67010000000000000083161562000c8e57680100b1afa5abcbed6102831c62000c8e565b68010163da9fb33356d802831c62001469565b680102c9a3e778060ee702831c62001458565b6801059b0d31585743ae02831c62001447565b68010b5586cf9890f62a02831c62001436565b6801172b83c7d517adce02831c62001425565b6801306fe0a31b7152df02831c62001414565b5068016a09e667f3bcc909607f1b62001403565b60249060405190626c1a0560e31b82526004820152fdfe6040608081526004908136101561001557600080fd5b600091823560e01c80630aa58b2114610ad8578063125d702014610aa25780631701121814610a785780631cf8287d1461062e5780631d0806ae1461060757806329c234df146105b55780632a00654a14610582578063343bba7f146105515780634ca2d2e81461051657806360893f42146104d557806367e828bf146104915780636daf390b1461044d5780637240d8941461041257806378d0733b146103e45780637ed9038b146103bf57806396afc450146103985780639f6fec9014610317578063a1ac14f6146102e7578063b8824a85146102c3578063b976c91e14610288578063d0202d3b14610244578063d2ca2115146102055763d4b839921461011e57600080fd5b34610201578260031936011261020157815163700f04ef60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169282019290925291602083602481877f000000000000000000000000000000000000000000000000000000000000000087165af19283156101f75784936101b3575b50602093505191168152f35b9092506020813d82116101ef575b816101ce60209383610b45565b810103126101eb575181811681036101eb576020935091386101a7565b8380fd5b3d91506101c1565b81513d86823e3d90fd5b8280fd5b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5080fd5b505034610240578160031936011261024057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102405781600319360112610240576020906102e0610b83565b9051908152f35b505034610240578160031936011261024057602090610304611303565b6001600160681b03600154169051908152f35b505034610240578160031936011261024057602090610334611303565b6102e061033f611743565b61039361036d7f00000000000000000000000000000000000000000000000000000000000000008093611325565b7f0000000000000000000000000000000000000000000000000000000000000000610fa3565b610fa3565b5050346102405781600319360112610240576020906103b5611303565b6002549051908152f35b5050346102405781600319360112610240576020906103dc611303565b6102e0610fb0565b5050346102405781600319360112610240576001600160681b03602092610409611303565b54169051908152f35b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610240578160031936011261024057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610240578160031936011261024057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5050346102405781600319360112610240576020905163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102405781600319360112610240576001600160681b03602092610576611303565b5460681c169051908152f35b50503461024057816003193601126102405760209061059f611303565b6001600160681b0360015460681c169051908152f35b5050346102405781600319360112610240576020906105d2611303565b6102e061036d6105e0611743565b7f000000000000000000000000000000000000000000000000000000000000000090611325565b505034610240578160031936011261024057602090610624611303565b6003549051908152f35b509034610201576080366003190112610201576001600160a01b039180358381169190829003610a7457602494853590604435906064359367ffffffffffffffff90818611610201573660238701121561020157858101359561069087610b67565b9661069d8a519889610b45565b808852368c8284010111610a74578b93929181869260209e8f9301838c0137890101528715610a66576106ce611303565b600254998a15610a57576106e28b88611216565b9a8b15610a4157868c11610a26576107218c6107788a61078d610788670de0b6b3a7640000610782600154966107296001600160681b03998a92610c27565b828a16610bae565b1697600160681b600160d01b03906107619061074488610c27565b906cffffffffffffffffffffffffff198b168c1760681c16610bae565b60681b169861077d65ffffffffffff978897610d46565b610dad565b610e2b565b05610cf7565b610c90565b6001600160d01b03199384168517861760d01c911601908111610a145760d01b16911717600155807f000000000000000000000000000000000000000000000000000000000000000016928a5190637cc99d3f60e01b825233848301528a86830152827f0000000000000000000000000000000000000000000000000000000000000000166044830152886064830152868260848183895af191821561098e57908e918893610998575b5050508851610925575b833b15610921579185809593926108a28e9896948e51998a978896879563c8576e6160e01b87527f00000000000000000000000000000000000000000000000000000000000000001690860152840152606060448401526064830190610c02565b03925af19081156109165750907f6abc2d6699315cdd965afdaa01e9bfd32b512397f6ed431a17b64af87b2c3555939291610907575b50855191825287820152858582015260806060820152806108fe33946080830190610c02565b0390a351908152f35b61091090610b1b565b386108d8565b8751903d90823e3d90fd5b8580fd5b893b156109215787868d8c888f888f61096a908793519889978896879563a5a6edad60e01b875233908701528501526044840152608060648401526084830190610c02565b03925af1801561098e5761097f575b50610841565b61098890610b1b565b38610979565b8c513d89823e3d90fd5b909192503d8089833e6109ab8183610b45565b81019281840312610a0c578051918211610a0c57019080601f83011215610a1057818e918d9351926109e86109df85610b67565b95519586610b45565b8385528383010111610a0c5790610a04918f8085019101610bdf565b8c3880610837565b8780fd5b8680fd5b634e487b7160e01b8952601186528789fd5b6044838d878a8f5193636abde48d60e11b8552840152820152fd5b8a5163c7c021f760e01b81528084018990528590fd5b508851635192c35d60e01b8152fd5b885163038f175f60e21b8152fd5b8480fd5b505034610240578160031936011261024057602090610a95611303565b60015460d01c9051908152f35b505034610240578160031936011261024057602090610abf611303565b670de0b6b3a7640000610ad06111d6565b059051908152f35b509134610b18576020366003190112610b185750610af4611303565b6002548015610b0a576102e09060209335611216565b5051635192c35d60e01b8152fd5b80fd5b67ffffffffffffffff8111610b2f57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610b2f57604052565b67ffffffffffffffff8111610b2f57601f01601f191660200190565b610b8b611303565b6002548015610ba857610ba590610ba0610fb0565b611216565b90565b50600090565b9190916001600160681b0380809416911601918211610bc957565b634e487b7160e01b600052601160045260246000fd5b60005b838110610bf25750506000910152565b8181015183820152602001610be2565b90602091610c1b81518092818552858086019101610bdf565b601f01601f1916010190565b6001600160681b0390818111610c3b571690565b60405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663034206269747360c81b6064820152608490fd5b65ffffffffffff90818111610ca3571690565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b60008112610d025790565b606460405162461bcd60e51b815260206004820152602060248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152fd5b6001600160ff1b038111610d575790565b60405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608490fd5b7809392ee8e921d5d073aff322e62439fcf32d7f344649470f8f198112610e13577809392ee8e921d5d073aff322e62439fcf32d7f344649470f908113610dfb57670de0b6b3a76400000290565b60249060405190639d58109160e01b82526004820152fd5b602490604051906399474eeb60e01b82526004820152fd5b90600160ff1b808314908115610ec9575b50610eb7576000821215610eae57610e65826000035b6000831215610ea7578260000390610ef3565b916001600160ff1b038311610e8a5760009160001991181315610e86575090565b0390565b6044916040519163d49c26b360e01b835260048301526024820152fd5b8290610ef3565b610e6582610e52565b6040516309fe2b4560e41b8152600490fd5b9050811438610e3c565b8115610edd570490565b634e487b7160e01b600052601260045260246000fd5b670de0b6b3a7640000916000198383099280830292838086109503948086039514610f965782851015610f7357908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b8260649260405192630c740aef60e31b8452600484015260248301526044820152fd5b505090610ba59250610ed3565b91908201809211610bc957565b610fd0670de0b6b3a7640000610782600254610fca6111d6565b9061109c565b6040519063587e7b1360e11b825260018060a01b03807f0000000000000000000000000000000000000000000000000000000000000000166004840152602083602481600080957f0000000000000000000000000000000000000000000000000000000000000000165af192831561108f57819361105c575b505081811115611057575090565b905090565b9092506020813d8211611087575b8161107760209383610b45565b8101031261020157519138611049565b3d915061106a565b50604051903d90823e3d90fd5b90600160ff1b808314908115611136575b5061112457600082121561111b576110d6826000035b6000831215611114578260000390611140565b916001600160ff1b0383116110f75760009160001991181315610e86575090565b6044916040519163120b5b4360e01b835260048301526024820152fd5b8290611140565b6110d6826110c3565b60405163a6070c2560e01b8152600490fd5b90508114386110ad565b909190600019838209838202918280831092039180830392146111c557670de0b6b3a764000090818310156111a757947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b6044908660405191635173648d60e01b835260048301526024820152fd5b5050670de0b6b3a764000090049150565b60015460d01c804210610ba8576111fb6107786111f561077842610d46565b92610d46565b9060008282039212818312811691831390151617610bc95790565b9081156112fc57611225610fb0565b8083116112de575090611272916112466107786112406111d6565b93610d46565b90600354907f00000000000000000000000000000000000000000000000000000000000000009261179f565b906000670afdc366fbc00000600160ff1b0383136112c557610ba59192670de0b6b3a7640000809281830780156000146112af5750505005610cf7565b830392136112be575b50610782565b01816112b8565b604051631d0bee6360e21b815260048101849052602490fd5b826044916040519163c4086e6560e01b835260048301526024820152fd5b5050600090565b61130b611743565b60005460d01c810361131a5750565b61132390611338565b565b81810292918115918404141715610bc957565b7f000000000000000000000000000000000000000000000000000000000000000080421061173f57600154916001600160681b0390818416600081151580611731575b1561171b5750600080546001600160d01b0319168217600160681b600160d01b038716178155909460681c8316939091905b82546001600160d01b031660d083901b6001600160d01b03199081169190911784557f00000000000000000000000000000000000000000000000000000000000000009161140990610788906114038686611325565b90610fa3565b60d01b1660015560405163587e7b1360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602094859183916024918391907f0000000000000000000000000000000000000000000000000000000000000000165af190811561170f576000916116e2575b50807f00000000000000000000000000000000000000000000000000000000000000008110156116b85750506114cf6114c96107786000610d46565b91610d46565b8060030b90810361166457906114e76114ed92610dad565b90610e2b565b600281905593841561162d5761152b61077863ffffffff7f000000000000000000000000000000000000000000000000000000000000000016610d46565b94611536818761109c565b9461155f8661155a61154c610778858d16610d46565b6114e7610778868916610d46565b61109c565b946115a46115988461077d61159d6115987f00000000000000000000000000000000000000000000000000000000000000009d8e61109c565b6117f4565b9a8c61109c565b96670de0b6b3a763ffff198801978813600116610bc9577f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a0398610fca65ffffffffffff986115f760a09b6115fd95610e2b565b9261109c565b6003555b60015460d01c9160035494816040519b168b5216908901526040880152606087015260808601521692a2565b7f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a039460a09465ffffffffffff946000600355611601565b60405162461bcd60e51b815260048101859052602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b6114cf916114c991610778916001600160c01b039081106116da575b50610d46565b9050386116d4565b908482813d8311611708575b6116f88183610b45565b81010312610b185750513861148d565b503d6116ee565b6040513d6000823e3d90fd5b54838116955060681c83169360009291506113ad565b50838660681c16151561137b565b5050565b7f0000000000000000000000000000000000000000000000000000000000000000804210610ba8574203428111610bc957610ba5907f000000000000000000000000000000000000000000000000000000000000000090610ed3565b80156117ea576117b69161077d611598928661109c565b91670de0b6b3a763ffff198301928313600116610bc9576117e4610fca926114e7611598610ba5978561109c565b92610e2b565b5050505050600090565b68023f3bfb6373f0ffff198112610ba857680736ea4425c11ac630811361183257670de0b6b3a76400006714057b7ef767814f610ba5920205611864565b6024906040519063ca7ec0c560e01b82526004820152fd5b8015610edd576ec097ce7bc90715b34b9f10000000000590565b60008112156118935768033dd1780914b97114198112610ba85761188a90600003611864565b610ba59061184a565b680a688906bd8affffff81136120c757670de0b6b3a764000080604092831b0590600160bf1b67ff000000000000008316611fb6575b66ff0000000000008316611eae575b65ff00000000008316611dae575b64ff000000008316611cb6575b63ff0000008316611bc6575b62ff00008316611ade575b61ff0083166119fe575b60ff8316611927575b02911c60bf031c90565b608083166119ec575b8383166119da575b602083166119c8575b601083166119b6575b600883166119a4575b60048316611992575b60028316611980575b600183161561191d576801000000000000000102831c61191d565b6801000000000000000102831c611965565b6801000000000000000302831c61195c565b6801000000000000000602831c611953565b6801000000000000000b02831c61194a565b6801000000000000001602831c611941565b6801000000000000002c02831c611938565b6801000000000000005902831c611930565b6180008316611acc575b6140008316611aba575b6120008316611aa8575b6110008316611a96575b6108008316611a84575b6104008316611a72575b6102008316611a60575b61010083161561191457680100000000000000b102831c611914565b6801000000000000016302831c611a44565b680100000000000002c602831c611a3a565b6801000000000000058c02831c611a30565b68010000000000000b1702831c611a26565b6801000000000000162e02831c611a1c565b68010000000000002c5d02831c611a12565b680100000000000058b902831c611a08565b628000008316611bb4575b624000008316611ba2575b622000008316611b90575b621000008316611b7e575b620800008316611b6c575b620400008316611b5a575b620200008316611b48575b6201000083161561190a576801000000000000b17202831c61190a565b680100000000000162e402831c611b2b565b6801000000000002c5c802831c611b20565b68010000000000058b9102831c611b15565b680100000000000b172102831c611b0a565b68010000000000162e4302831c611aff565b680100000000002c5c8602831c611af4565b6801000000000058b90c02831c611ae9565b63800000008316611ca4575b63400000008316611c92575b63200000008316611c80575b63100000008316611c6e575b63080000008316611c5c575b63040000008316611c4a575b63020000008316611c38575b63010000008316156118ff5768010000000000b1721802831c6118ff565b6801000000000162e43002831c611c1a565b68010000000002c5c86002831c611c0e565b680100000000058b90c002831c611c02565b6801000000000b17217f02831c611bf6565b680100000000162e42ff02831c611bea565b6801000000002c5c85fe02831c611bde565b68010000000058b90bfc02831c611bd2565b6480000000008316611d9c575b6440000000008316611d8a575b6420000000008316611d78575b6410000000008316611d66575b6408000000008316611d54575b6404000000008316611d42575b6402000000008316611d30575b6401000000008316156118f357680100000000b17217f802831c6118f3565b68010000000162e42ff102831c611d11565b680100000002c5c85fe302831c611d04565b6801000000058b90bfce02831c611cf7565b68010000000b17217fbb02831c611cea565b6801000000162e42fff002831c611cdd565b68010000002c5c8601cc02831c611cd0565b680100000058b90c0b4902831c611cc3565b658000000000008316611e9c575b654000000000008316611e8a575b652000000000008316611e78575b651000000000008316611e66575b650800000000008316611e54575b650400000000008316611e42575b650200000000008316611e30575b650100000000008316156118e6576801000000b17218355102831c6118e6565b680100000162e430e5a202831c611e10565b6801000002c5c863b73f02831c611e02565b68010000058b90cf1e6e02831c611df4565b680100000b1721bcfc9a02831c611de6565b68010000162e43f4f83102831c611dd8565b680100002c5c89d5ec6d02831c611dca565b6801000058b91b5bc9ae02831c611dbc565b66800000000000008316611fa4575b66400000000000008316611f92575b66200000000000008316611f80575b66100000000000008316611f6e575b66080000000000008316611f5c575b66040000000000008316611f4a575b66020000000000008316611f38575b66010000000000008316156118d85768010000b17255775c0402831c6118d8565b6801000162e525ee054702831c611f17565b68010002c5cc37da949202831c611f08565b680100058ba01fb9f96d02831c611ef9565b6801000b175effdc76ba02831c611eea565b680100162f3904051fa102831c611edb565b6801002c605e2e8cec5002831c611ecc565b68010058c86da1c09ea202831c611ebd565b67800000000000000083166120b4575b67400000000000000083166120a2575b6720000000000000008316612090575b671000000000000000831661207e575b670800000000000000831661206c575b670400000000000000831661205a575b6702000000000000008316612048575b6701000000000000008316156118c957680100b1afa5abcbed6102831c6118c9565b68010163da9fb33356d802831c612026565b680102c9a3e778060ee702831c612016565b6801059b0d31585743ae02831c612006565b68010b5586cf9890f62a02831c611ff6565b6801172b83c7d517adce02831c611fe6565b6801306fe0a31b7152df02831c611fd6565b5068016a09e667f3bcc909607f1b611fc6565b60249060405190626c1a0560e31b82526004820152fdfea264697066735822122005645221b55e89a6c9c9d5569339b4cb77bde62c45ef7c9f6727c81e5e81d2a764736f6c63430008130033a26469706673582212208a12122378650ce9eabc01ced9a53e143525beb72780052238a3b54bda6b893a64736f6c63430008130033
Deployed Bytecode
0x604060808152600490813610156200001657600080fd5b600090813560e01c80631e3dd18b14620002c45780635d8c32a914620002a65780639cded5ab14620002645763f228d46b146200005257600080fd5b346200026057610140918260031936011262000255576001600160a01b03928435848116908190036200025c5760243591858316809303620002585760443593868516809503620002555760643563ffffffff8082168092036200025c57608435818116809103620002585760a435918216809203620002585760e435926cffffffffffffffffffffffffff9485851680950362000255576101043595861680960362000255578a51610124359761363f8083019067ffffffffffffffff8211848310176200024057908d8f8e8e8795620003558739845260208401528201528560608201528660808201528760a082015260c43560c08201528860e0820152896101008201528a61012082015203019082f08015620002345781546801000000000000000081101562000221578d9e50908160018e9f9c9d9e94930183556200019c9062000309565b9b9091169e8f9b82549060031b918d831b921b191617905589815260016020522060ff1981541660011790558a51968752602087015289860152606085015260c435608085015260a084015260c083015260e08201526101007f955594a69091ec47a9c770953195b25368e20e0c19791ccc001cdfdd6076555791a451908152602090f35b634e487b7160e01b835260418f52602483fd5b508a51903d90823e3d90fd5b508f846041602492634e487b7160e01b835252fd5b80fd5b8380fd5b8280fd5b5080fd5b5082346200025c5760203660031901126200025c57356001600160a01b038116908190036200025c57818360ff92602095526001855220541690519015158152f35b50346200026057816003193601126200026057602091549051908152f35b5082346200025c5760203660031901126200025c5735918054831015620002555750620002f360209262000309565b905491519160018060a01b039160031b1c168152f35b90600091825481101562000340578280527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563019190565b634e487b7160e01b83526032600452602483fdfe610180604081815234620003ae5781906200363f8038038091620000248286620003b3565b843961014092839181010312620003ae578251916001600160a01b038084169290838503620003ae5785946200005d60208701620003ed565b6200006a848801620003ed565b90620000796060890162000402565b916200008860808a0162000402565b926200009760a08b0162000402565b9160c08b015193620000ac60e08d0162000414565b96620000bd6101009e8f0162000414565b98610120809e01519c156200039d57808316156200038c578316156200037b5760805260a05260c05260e083905263ffffffff908116808c529381168a529087529162000115906200010f9062000429565b62000491565b90680736ea4425c11ac630806200012d848462000679565b13620002b557505050845116875180821015620002985750506001600160681b0390811690811562000287578216156200027657600080546001600160d01b0319169190911760689290921b600160681b600160d01b03169190911790556101609283526200019b620007c1565b519261211494856200152b8639608051858181610176015281816104a6015281816107b701528181611019015261145c015260a05185818161014401528181610462015261086a015260c051858181610259015281816107f201528181610fe80152611427015260e05185818161052e0152818161124d015261157201525184818161021d01528181610347015281816105e2015281816113d1015261177a0152518381816102a00152818161036f0152818161133a01526117450152518281816104f2015261150601525181818161042a01526114910152f35b825163427fe21b60e01b8152600490fd5b83516340561e0d60e01b8152600490fd5b6044925084519163a3f8209f60e01b835260048301526024820152fd5b869190600160ff1b84146200036a576000841215620003635783600003935b84156200034d576044946f641f188c35bc17242856994ebac0000004916001600160ff1b0383116200033257600091600019911813156200032a5750915b5191635357a16160e11b835260048301526024820152fd5b039162000312565b859185519163d49c26b360e01b835260048301526024820152fd5b634e487b7160e01b600052601260045260246000fd5b83620002d4565b82516309fe2b4560e41b8152600490fd5b895163104ccf9960e21b8152600490fd5b8a5163edf0381360e01b8152600490fd5b8a51637cee330760e11b8152600490fd5b600080fd5b601f909101601f19168101906001600160401b03821190821017620003d757604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620003ae57565b519063ffffffff82168203620003ae57565b51906001600160681b0382168203620003ae57565b6001600160ff1b0381116200043b5790565b60405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608490fd5b7809392ee8e921d5d073aff322e62439fcf32d7f344649470f8f198112620004f9577809392ee8e921d5d073aff322e62439fcf32d7f344649470f908113620004e157670de0b6b3a76400000290565b60249060405190639d58109160e01b82526004820152fd5b602490604051906399474eeb60e01b82526004820152fd5b90600160ff1b808314908115620005ba575b50620005a85760008212156200059d5762000551826000035b600083121562000595578260000390620005c5565b916001600160ff1b03831162000578576000916000199118131562000574575090565b0390565b6044916040519163d49c26b360e01b835260048301526024820152fd5b8290620005c5565b62000551826200053c565b6040516309fe2b4560e41b8152600490fd5b905081143862000523565b670de0b6b3a76400009160001983830992808302928380861095039480860395146200066a57828510156200064757908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b8260649260405192630c740aef60e31b8452600484015260248301526044820152fd5b5050809250156200034d570490565b90600160ff1b8083149081156200071e575b506200070c5760008212156200070157620006b9826000035b6000831215620006f957826000039062000729565b916001600160ff1b038311620006dc576000916000199118131562000574575090565b6044916040519163120b5b4360e01b835260048301526024820152fd5b829062000729565b620006b982620006a4565b60405163a6070c2560e01b8152600490fd5b90508114386200068b565b90919060001983820983820291828083109203918083039214620007b057670de0b6b3a764000090818310156200079257947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b6044908660405191635173648d60e01b835260048301526024820152fd5b5050670de0b6b3a764000090049150565b6101205180421062000ba057600154906001600160681b039081831660008115158062000b91575b1562000b7d5750600080546001600160d01b0319168217600160681b600160d01b03861617905560689390931c8216925b600080546001600160d01b031690556101008051156001171562000a1b5765ffffffffffff831162000b295760d09290921b6001600160d01b03191660015560805160c05160405163587e7b1360e11b81526001600160a01b039182166004820152602094929091859183916024918391600091165af190811562000b1d5760009162000ae7575b508061016051821060001462000ab7575050620008d0620008c86200010f600062000429565b915162000429565b8060030b90810362000a635790620008ec620008f39262000491565b9062000511565b600281905593841562000a3157620009186200010f63ffffffff610140511662000429565b9462000925818762000679565b94620009578662000951620009406200010f85891662000429565b620008ec6200010f86891662000429565b62000679565b946200098c6200097884620009866200097e6200097860e0519d8e62000679565b62000ba3565b9a8c62000679565b62000511565b96670de0b6b3a763ffff19880197881360011662000a1b57600098620009e660a098620009df7f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a039b620009ed9562000511565b9262000679565b9062000679565b6003555b60015460d01c916003549481604051971687521690850152604084015260608301526080820152a2565b634e487b7160e01b600052601160045260246000fd5b6000947f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a039460a09487600355620009f1565b60405162461bcd60e51b815260048101859052602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b620008d091620008c8916200010f916001600160c01b0390811062000ade575b5062000429565b90503862000ad7565b908482813d831162000b15575b62000b008183620003b3565b8101031262000b1257505138620008a2565b80fd5b503d62000af4565b6040513d6000823e3d90fd5b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b54606881901c84169450831690506200081a565b50838560681c161515620007e9565b50565b68023f3bfb6373f0ffff19811262000c0057680736ea4425c11ac630811362000be857670de0b6b3a76400006714057b7ef767814f62000be592020562000c21565b90565b6024906040519063ca7ec0c560e01b82526004820152fd5b50600090565b80156200034d576ec097ce7bc90715b34b9f10000000000590565b600081121562000c565768033dd1780914b9711419811262000c005762000c4b9060000362000c21565b62000be59062000c06565b680a688906bd8affffff81136200151357670de0b6b3a764000080604092831b0590600160bf1b67ff000000000000008316620013f2575b66ff0000000000008316620012da575b65ff00000000008316620011ca575b64ff000000008316620010c2575b63ff000000831662000fc2575b62ff0000831662000eca575b61ff00831662000dda575b60ff831662000cf3575b02911c60bf031c90565b6080831662000dc7575b83831662000db4575b6020831662000da1575b6010831662000d8e575b6008831662000d7b575b6004831662000d68575b6002831662000d55575b600183161562000ce9576801000000000000000102831c62000ce9565b6801000000000000000102831c62000d38565b6801000000000000000302831c62000d2e565b6801000000000000000602831c62000d24565b6801000000000000000b02831c62000d1a565b6801000000000000001602831c62000d10565b6801000000000000002c02831c62000d06565b6801000000000000005902831c62000cfd565b618000831662000eb7575b614000831662000ea4575b612000831662000e91575b611000831662000e7e575b610800831662000e6b575b610400831662000e58575b610200831662000e45575b61010083161562000cdf57680100000000000000b102831c62000cdf565b6801000000000000016302831c62000e27565b680100000000000002c602831c62000e1c565b6801000000000000058c02831c62000e11565b68010000000000000b1702831c62000e06565b6801000000000000162e02831c62000dfb565b68010000000000002c5d02831c62000df0565b680100000000000058b902831c62000de5565b62800000831662000faf575b62400000831662000f9c575b62200000831662000f89575b62100000831662000f76575b62080000831662000f63575b62040000831662000f50575b62020000831662000f3d575b6201000083161562000cd4576801000000000000b17202831c62000cd4565b680100000000000162e402831c62000f1e565b6801000000000002c5c802831c62000f12565b68010000000000058b9102831c62000f06565b680100000000000b172102831c62000efa565b68010000000000162e4302831c62000eee565b680100000000002c5c8602831c62000ee2565b6801000000000058b90c02831c62000ed6565b63800000008316620010af575b634000000083166200109c575b6320000000831662001089575b6310000000831662001076575b6308000000831662001063575b6304000000831662001050575b630200000083166200103d575b630100000083161562000cc85768010000000000b1721802831c62000cc8565b6801000000000162e43002831c6200101d565b68010000000002c5c86002831c62001010565b680100000000058b90c002831c62001003565b6801000000000b17217f02831c62000ff6565b680100000000162e42ff02831c62000fe9565b6801000000002c5c85fe02831c62000fdc565b68010000000058b90bfc02831c62000fcf565b6480000000008316620011b7575b6440000000008316620011a4575b642000000000831662001191575b64100000000083166200117e575b64080000000083166200116b575b640400000000831662001158575b640200000000831662001145575b64010000000083161562000cbb57680100000000b17217f802831c62000cbb565b68010000000162e42ff102831c62001124565b680100000002c5c85fe302831c62001116565b6801000000058b90bfce02831c62001108565b68010000000b17217fbb02831c620010fa565b6801000000162e42fff002831c620010ec565b68010000002c5c8601cc02831c620010de565b680100000058b90c0b4902831c620010d0565b658000000000008316620012c7575b654000000000008316620012b4575b652000000000008316620012a1575b6510000000000083166200128e575b6508000000000083166200127b575b65040000000000831662001268575b65020000000000831662001255575b6501000000000083161562000cad576801000000b17218355102831c62000cad565b680100000162e430e5a202831c62001233565b6801000002c5c863b73f02831c62001224565b68010000058b90cf1e6e02831c62001215565b680100000b1721bcfc9a02831c62001206565b68010000162e43f4f83102831c620011f7565b680100002c5c89d5ec6d02831c620011e8565b6801000058b91b5bc9ae02831c620011d9565b66800000000000008316620013df575b66400000000000008316620013cc575b66200000000000008316620013b9575b66100000000000008316620013a6575b6608000000000000831662001393575b6604000000000000831662001380575b660200000000000083166200136d575b660100000000000083161562000c9e5768010000b17255775c0402831c62000c9e565b6801000162e525ee054702831c6200134a565b68010002c5cc37da949202831c6200133a565b680100058ba01fb9f96d02831c6200132a565b6801000b175effdc76ba02831c6200131a565b680100162f3904051fa102831c6200130a565b6801002c605e2e8cec5002831c620012fa565b68010058c86da1c09ea202831c620012ea565b6780000000000000008316620014ff575b6740000000000000008316620014ec575b6720000000000000008316620014d9575b6710000000000000008316620014c6575b6708000000000000008316620014b3575b6704000000000000008316620014a0575b67020000000000000083166200148d575b67010000000000000083161562000c8e57680100b1afa5abcbed6102831c62000c8e565b68010163da9fb33356d802831c62001469565b680102c9a3e778060ee702831c62001458565b6801059b0d31585743ae02831c62001447565b68010b5586cf9890f62a02831c62001436565b6801172b83c7d517adce02831c62001425565b6801306fe0a31b7152df02831c62001414565b5068016a09e667f3bcc909607f1b62001403565b60249060405190626c1a0560e31b82526004820152fdfe6040608081526004908136101561001557600080fd5b600091823560e01c80630aa58b2114610ad8578063125d702014610aa25780631701121814610a785780631cf8287d1461062e5780631d0806ae1461060757806329c234df146105b55780632a00654a14610582578063343bba7f146105515780634ca2d2e81461051657806360893f42146104d557806367e828bf146104915780636daf390b1461044d5780637240d8941461041257806378d0733b146103e45780637ed9038b146103bf57806396afc450146103985780639f6fec9014610317578063a1ac14f6146102e7578063b8824a85146102c3578063b976c91e14610288578063d0202d3b14610244578063d2ca2115146102055763d4b839921461011e57600080fd5b34610201578260031936011261020157815163700f04ef60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169282019290925291602083602481877f000000000000000000000000000000000000000000000000000000000000000087165af19283156101f75784936101b3575b50602093505191168152f35b9092506020813d82116101ef575b816101ce60209383610b45565b810103126101eb575181811681036101eb576020935091386101a7565b8380fd5b3d91506101c1565b81513d86823e3d90fd5b8280fd5b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5080fd5b505034610240578160031936011261024057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102405781600319360112610240576020906102e0610b83565b9051908152f35b505034610240578160031936011261024057602090610304611303565b6001600160681b03600154169051908152f35b505034610240578160031936011261024057602090610334611303565b6102e061033f611743565b61039361036d7f00000000000000000000000000000000000000000000000000000000000000008093611325565b7f0000000000000000000000000000000000000000000000000000000000000000610fa3565b610fa3565b5050346102405781600319360112610240576020906103b5611303565b6002549051908152f35b5050346102405781600319360112610240576020906103dc611303565b6102e0610fb0565b5050346102405781600319360112610240576001600160681b03602092610409611303565b54169051908152f35b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610240578160031936011261024057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610240578160031936011261024057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5050346102405781600319360112610240576020905163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b505034610240578160031936011261024057602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102405781600319360112610240576001600160681b03602092610576611303565b5460681c169051908152f35b50503461024057816003193601126102405760209061059f611303565b6001600160681b0360015460681c169051908152f35b5050346102405781600319360112610240576020906105d2611303565b6102e061036d6105e0611743565b7f000000000000000000000000000000000000000000000000000000000000000090611325565b505034610240578160031936011261024057602090610624611303565b6003549051908152f35b509034610201576080366003190112610201576001600160a01b039180358381169190829003610a7457602494853590604435906064359367ffffffffffffffff90818611610201573660238701121561020157858101359561069087610b67565b9661069d8a519889610b45565b808852368c8284010111610a74578b93929181869260209e8f9301838c0137890101528715610a66576106ce611303565b600254998a15610a57576106e28b88611216565b9a8b15610a4157868c11610a26576107218c6107788a61078d610788670de0b6b3a7640000610782600154966107296001600160681b03998a92610c27565b828a16610bae565b1697600160681b600160d01b03906107619061074488610c27565b906cffffffffffffffffffffffffff198b168c1760681c16610bae565b60681b169861077d65ffffffffffff978897610d46565b610dad565b610e2b565b05610cf7565b610c90565b6001600160d01b03199384168517861760d01c911601908111610a145760d01b16911717600155807f000000000000000000000000000000000000000000000000000000000000000016928a5190637cc99d3f60e01b825233848301528a86830152827f0000000000000000000000000000000000000000000000000000000000000000166044830152886064830152868260848183895af191821561098e57908e918893610998575b5050508851610925575b833b15610921579185809593926108a28e9896948e51998a978896879563c8576e6160e01b87527f00000000000000000000000000000000000000000000000000000000000000001690860152840152606060448401526064830190610c02565b03925af19081156109165750907f6abc2d6699315cdd965afdaa01e9bfd32b512397f6ed431a17b64af87b2c3555939291610907575b50855191825287820152858582015260806060820152806108fe33946080830190610c02565b0390a351908152f35b61091090610b1b565b386108d8565b8751903d90823e3d90fd5b8580fd5b893b156109215787868d8c888f888f61096a908793519889978896879563a5a6edad60e01b875233908701528501526044840152608060648401526084830190610c02565b03925af1801561098e5761097f575b50610841565b61098890610b1b565b38610979565b8c513d89823e3d90fd5b909192503d8089833e6109ab8183610b45565b81019281840312610a0c578051918211610a0c57019080601f83011215610a1057818e918d9351926109e86109df85610b67565b95519586610b45565b8385528383010111610a0c5790610a04918f8085019101610bdf565b8c3880610837565b8780fd5b8680fd5b634e487b7160e01b8952601186528789fd5b6044838d878a8f5193636abde48d60e11b8552840152820152fd5b8a5163c7c021f760e01b81528084018990528590fd5b508851635192c35d60e01b8152fd5b885163038f175f60e21b8152fd5b8480fd5b505034610240578160031936011261024057602090610a95611303565b60015460d01c9051908152f35b505034610240578160031936011261024057602090610abf611303565b670de0b6b3a7640000610ad06111d6565b059051908152f35b509134610b18576020366003190112610b185750610af4611303565b6002548015610b0a576102e09060209335611216565b5051635192c35d60e01b8152fd5b80fd5b67ffffffffffffffff8111610b2f57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610b2f57604052565b67ffffffffffffffff8111610b2f57601f01601f191660200190565b610b8b611303565b6002548015610ba857610ba590610ba0610fb0565b611216565b90565b50600090565b9190916001600160681b0380809416911601918211610bc957565b634e487b7160e01b600052601160045260246000fd5b60005b838110610bf25750506000910152565b8181015183820152602001610be2565b90602091610c1b81518092818552858086019101610bdf565b601f01601f1916010190565b6001600160681b0390818111610c3b571690565b60405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663034206269747360c81b6064820152608490fd5b65ffffffffffff90818111610ca3571690565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b60008112610d025790565b606460405162461bcd60e51b815260206004820152602060248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152fd5b6001600160ff1b038111610d575790565b60405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608490fd5b7809392ee8e921d5d073aff322e62439fcf32d7f344649470f8f198112610e13577809392ee8e921d5d073aff322e62439fcf32d7f344649470f908113610dfb57670de0b6b3a76400000290565b60249060405190639d58109160e01b82526004820152fd5b602490604051906399474eeb60e01b82526004820152fd5b90600160ff1b808314908115610ec9575b50610eb7576000821215610eae57610e65826000035b6000831215610ea7578260000390610ef3565b916001600160ff1b038311610e8a5760009160001991181315610e86575090565b0390565b6044916040519163d49c26b360e01b835260048301526024820152fd5b8290610ef3565b610e6582610e52565b6040516309fe2b4560e41b8152600490fd5b9050811438610e3c565b8115610edd570490565b634e487b7160e01b600052601260045260246000fd5b670de0b6b3a7640000916000198383099280830292838086109503948086039514610f965782851015610f7357908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b8260649260405192630c740aef60e31b8452600484015260248301526044820152fd5b505090610ba59250610ed3565b91908201809211610bc957565b610fd0670de0b6b3a7640000610782600254610fca6111d6565b9061109c565b6040519063587e7b1360e11b825260018060a01b03807f0000000000000000000000000000000000000000000000000000000000000000166004840152602083602481600080957f0000000000000000000000000000000000000000000000000000000000000000165af192831561108f57819361105c575b505081811115611057575090565b905090565b9092506020813d8211611087575b8161107760209383610b45565b8101031261020157519138611049565b3d915061106a565b50604051903d90823e3d90fd5b90600160ff1b808314908115611136575b5061112457600082121561111b576110d6826000035b6000831215611114578260000390611140565b916001600160ff1b0383116110f75760009160001991181315610e86575090565b6044916040519163120b5b4360e01b835260048301526024820152fd5b8290611140565b6110d6826110c3565b60405163a6070c2560e01b8152600490fd5b90508114386110ad565b909190600019838209838202918280831092039180830392146111c557670de0b6b3a764000090818310156111a757947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b6044908660405191635173648d60e01b835260048301526024820152fd5b5050670de0b6b3a764000090049150565b60015460d01c804210610ba8576111fb6107786111f561077842610d46565b92610d46565b9060008282039212818312811691831390151617610bc95790565b9081156112fc57611225610fb0565b8083116112de575090611272916112466107786112406111d6565b93610d46565b90600354907f00000000000000000000000000000000000000000000000000000000000000009261179f565b906000670afdc366fbc00000600160ff1b0383136112c557610ba59192670de0b6b3a7640000809281830780156000146112af5750505005610cf7565b830392136112be575b50610782565b01816112b8565b604051631d0bee6360e21b815260048101849052602490fd5b826044916040519163c4086e6560e01b835260048301526024820152fd5b5050600090565b61130b611743565b60005460d01c810361131a5750565b61132390611338565b565b81810292918115918404141715610bc957565b7f000000000000000000000000000000000000000000000000000000000000000080421061173f57600154916001600160681b0390818416600081151580611731575b1561171b5750600080546001600160d01b0319168217600160681b600160d01b038716178155909460681c8316939091905b82546001600160d01b031660d083901b6001600160d01b03199081169190911784557f00000000000000000000000000000000000000000000000000000000000000009161140990610788906114038686611325565b90610fa3565b60d01b1660015560405163587e7b1360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602094859183916024918391907f0000000000000000000000000000000000000000000000000000000000000000165af190811561170f576000916116e2575b50807f00000000000000000000000000000000000000000000000000000000000000008110156116b85750506114cf6114c96107786000610d46565b91610d46565b8060030b90810361166457906114e76114ed92610dad565b90610e2b565b600281905593841561162d5761152b61077863ffffffff7f000000000000000000000000000000000000000000000000000000000000000016610d46565b94611536818761109c565b9461155f8661155a61154c610778858d16610d46565b6114e7610778868916610d46565b61109c565b946115a46115988461077d61159d6115987f00000000000000000000000000000000000000000000000000000000000000009d8e61109c565b6117f4565b9a8c61109c565b96670de0b6b3a763ffff198801978813600116610bc9577f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a0398610fca65ffffffffffff986115f760a09b6115fd95610e2b565b9261109c565b6003555b60015460d01c9160035494816040519b168b5216908901526040880152606087015260808601521692a2565b7f0fff8752be233efcf17757cb7cdaad191c96c300a446a60a74fb21b9ed9b8a039460a09465ffffffffffff946000600355611601565b60405162461bcd60e51b815260048101859052602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b6114cf916114c991610778916001600160c01b039081106116da575b50610d46565b9050386116d4565b908482813d8311611708575b6116f88183610b45565b81010312610b185750513861148d565b503d6116ee565b6040513d6000823e3d90fd5b54838116955060681c83169360009291506113ad565b50838660681c16151561137b565b5050565b7f0000000000000000000000000000000000000000000000000000000000000000804210610ba8574203428111610bc957610ba5907f000000000000000000000000000000000000000000000000000000000000000090610ed3565b80156117ea576117b69161077d611598928661109c565b91670de0b6b3a763ffff198301928313600116610bc9576117e4610fca926114e7611598610ba5978561109c565b92610e2b565b5050505050600090565b68023f3bfb6373f0ffff198112610ba857680736ea4425c11ac630811361183257670de0b6b3a76400006714057b7ef767814f610ba5920205611864565b6024906040519063ca7ec0c560e01b82526004820152fd5b8015610edd576ec097ce7bc90715b34b9f10000000000590565b60008112156118935768033dd1780914b97114198112610ba85761188a90600003611864565b610ba59061184a565b680a688906bd8affffff81136120c757670de0b6b3a764000080604092831b0590600160bf1b67ff000000000000008316611fb6575b66ff0000000000008316611eae575b65ff00000000008316611dae575b64ff000000008316611cb6575b63ff0000008316611bc6575b62ff00008316611ade575b61ff0083166119fe575b60ff8316611927575b02911c60bf031c90565b608083166119ec575b8383166119da575b602083166119c8575b601083166119b6575b600883166119a4575b60048316611992575b60028316611980575b600183161561191d576801000000000000000102831c61191d565b6801000000000000000102831c611965565b6801000000000000000302831c61195c565b6801000000000000000602831c611953565b6801000000000000000b02831c61194a565b6801000000000000001602831c611941565b6801000000000000002c02831c611938565b6801000000000000005902831c611930565b6180008316611acc575b6140008316611aba575b6120008316611aa8575b6110008316611a96575b6108008316611a84575b6104008316611a72575b6102008316611a60575b61010083161561191457680100000000000000b102831c611914565b6801000000000000016302831c611a44565b680100000000000002c602831c611a3a565b6801000000000000058c02831c611a30565b68010000000000000b1702831c611a26565b6801000000000000162e02831c611a1c565b68010000000000002c5d02831c611a12565b680100000000000058b902831c611a08565b628000008316611bb4575b624000008316611ba2575b622000008316611b90575b621000008316611b7e575b620800008316611b6c575b620400008316611b5a575b620200008316611b48575b6201000083161561190a576801000000000000b17202831c61190a565b680100000000000162e402831c611b2b565b6801000000000002c5c802831c611b20565b68010000000000058b9102831c611b15565b680100000000000b172102831c611b0a565b68010000000000162e4302831c611aff565b680100000000002c5c8602831c611af4565b6801000000000058b90c02831c611ae9565b63800000008316611ca4575b63400000008316611c92575b63200000008316611c80575b63100000008316611c6e575b63080000008316611c5c575b63040000008316611c4a575b63020000008316611c38575b63010000008316156118ff5768010000000000b1721802831c6118ff565b6801000000000162e43002831c611c1a565b68010000000002c5c86002831c611c0e565b680100000000058b90c002831c611c02565b6801000000000b17217f02831c611bf6565b680100000000162e42ff02831c611bea565b6801000000002c5c85fe02831c611bde565b68010000000058b90bfc02831c611bd2565b6480000000008316611d9c575b6440000000008316611d8a575b6420000000008316611d78575b6410000000008316611d66575b6408000000008316611d54575b6404000000008316611d42575b6402000000008316611d30575b6401000000008316156118f357680100000000b17217f802831c6118f3565b68010000000162e42ff102831c611d11565b680100000002c5c85fe302831c611d04565b6801000000058b90bfce02831c611cf7565b68010000000b17217fbb02831c611cea565b6801000000162e42fff002831c611cdd565b68010000002c5c8601cc02831c611cd0565b680100000058b90c0b4902831c611cc3565b658000000000008316611e9c575b654000000000008316611e8a575b652000000000008316611e78575b651000000000008316611e66575b650800000000008316611e54575b650400000000008316611e42575b650200000000008316611e30575b650100000000008316156118e6576801000000b17218355102831c6118e6565b680100000162e430e5a202831c611e10565b6801000002c5c863b73f02831c611e02565b68010000058b90cf1e6e02831c611df4565b680100000b1721bcfc9a02831c611de6565b68010000162e43f4f83102831c611dd8565b680100002c5c89d5ec6d02831c611dca565b6801000058b91b5bc9ae02831c611dbc565b66800000000000008316611fa4575b66400000000000008316611f92575b66200000000000008316611f80575b66100000000000008316611f6e575b66080000000000008316611f5c575b66040000000000008316611f4a575b66020000000000008316611f38575b66010000000000008316156118d85768010000b17255775c0402831c6118d8565b6801000162e525ee054702831c611f17565b68010002c5cc37da949202831c611f08565b680100058ba01fb9f96d02831c611ef9565b6801000b175effdc76ba02831c611eea565b680100162f3904051fa102831c611edb565b6801002c605e2e8cec5002831c611ecc565b68010058c86da1c09ea202831c611ebd565b67800000000000000083166120b4575b67400000000000000083166120a2575b6720000000000000008316612090575b671000000000000000831661207e575b670800000000000000831661206c575b670400000000000000831661205a575b6702000000000000008316612048575b6701000000000000008316156118c957680100b1afa5abcbed6102831c6118c9565b68010163da9fb33356d802831c612026565b680102c9a3e778060ee702831c612016565b6801059b0d31585743ae02831c612006565b68010b5586cf9890f62a02831c611ff6565b6801172b83c7d517adce02831c611fe6565b6801306fe0a31b7152df02831c611fd6565b5068016a09e667f3bcc909607f1b611fc6565b60249060405190626c1a0560e31b82526004820152fdfea264697066735822122005645221b55e89a6c9c9d5569339b4cb77bde62c45ef7c9f6727c81e5e81d2a764736f6c63430008130033a26469706673582212208a12122378650ce9eabc01ced9a53e143525beb72780052238a3b54bda6b893a64736f6c63430008130033
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.