add GSP
This commit is contained in:
195
contracts/DODOGasSavingPool/lib/DODOMath.sol
Normal file
195
contracts/DODOGasSavingPool/lib/DODOMath.sol
Normal file
@@ -0,0 +1,195 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
pragma solidity 0.8.16;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {DecimalMath} from "./DecimalMath.sol";
|
||||
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
||||
|
||||
/**
|
||||
* @title DODOMath
|
||||
* @author DODO Breeder
|
||||
*
|
||||
* @notice Functions for complex calculating. Including ONE Integration and TWO Quadratic solutions
|
||||
*/
|
||||
library DODOMath {
|
||||
using Math for uint256;
|
||||
/*
|
||||
Integrate dodo curve from V1 to V2
|
||||
require V0>=V1>=V2>0
|
||||
res = (1-k)i(V1-V2)+ikV0*V0(1/V2-1/V1)
|
||||
let V1-V2=delta
|
||||
res = i*delta*(1-k+k(V0^2/V1/V2))
|
||||
|
||||
i is the price of V-res trading pair
|
||||
|
||||
support k=1 & k=0 case
|
||||
|
||||
[round down]
|
||||
*/
|
||||
function _GeneralIntegrate(
|
||||
uint256 V0,
|
||||
uint256 V1,
|
||||
uint256 V2,
|
||||
uint256 i,
|
||||
uint256 k
|
||||
) internal pure returns (uint256) {
|
||||
require(V0 > 0, "TARGET_IS_ZERO");
|
||||
uint256 fairAmount = i * (V1 - V2); // i*delta
|
||||
if (k == 0) {
|
||||
return fairAmount / DecimalMath.ONE;
|
||||
}
|
||||
uint256 V0V0V1V2 = DecimalMath.divFloor(V0 * V0 / V1, V2);
|
||||
uint256 penalty = DecimalMath.mulFloor(k, V0V0V1V2); // k(V0^2/V1/V2)
|
||||
return (DecimalMath.ONE - k + penalty) * fairAmount / DecimalMath.ONE2;
|
||||
}
|
||||
|
||||
/*
|
||||
Follow the integration function above
|
||||
i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2)
|
||||
Assume Q2=Q0, Given Q1 and deltaB, solve Q0
|
||||
|
||||
i is the price of delta-V trading pair
|
||||
give out target of V
|
||||
|
||||
support k=1 & k=0 case
|
||||
|
||||
[round down]
|
||||
*/
|
||||
function _SolveQuadraticFunctionForTarget(
|
||||
uint256 V1,
|
||||
uint256 delta,
|
||||
uint256 i,
|
||||
uint256 k
|
||||
) internal pure returns (uint256) {
|
||||
if (k == 0) {
|
||||
return V1 + DecimalMath.mulFloor(i, delta);
|
||||
}
|
||||
// V0 = V1*(1+(sqrt-1)/2k)
|
||||
// sqrt = √(1+4kidelta/V1)
|
||||
// premium = 1+(sqrt-1)/2k
|
||||
// uint256 sqrt = (4 * k).mul(i).mul(delta).div(V1).add(DecimalMath.ONE2).sqrt();
|
||||
|
||||
if (V1 == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint256 sqrt;
|
||||
uint256 ki = 4 * k * i;
|
||||
|
||||
if (ki == 0) {
|
||||
sqrt = DecimalMath.ONE;
|
||||
} else if ((ki * delta) / ki == delta) {
|
||||
sqrt =((ki * delta) / V1 + DecimalMath.ONE2).sqrt();
|
||||
} else {
|
||||
sqrt = (ki / V1 * delta + DecimalMath.ONE2).sqrt();
|
||||
}
|
||||
uint256 premium =
|
||||
DecimalMath.divFloor(sqrt - DecimalMath.ONE, k * 2) + DecimalMath.ONE;
|
||||
// V0 is greater than or equal to V1 according to the solution
|
||||
return DecimalMath.mulFloor(V1, premium);
|
||||
}
|
||||
|
||||
/*
|
||||
Follow the integration expression above, we have:
|
||||
i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2)
|
||||
Given Q1 and deltaB, solve Q2
|
||||
This is a quadratic function and the standard version is
|
||||
aQ2^2 + bQ2 + c = 0, where
|
||||
a=1-k
|
||||
-b=(1-k)Q1-kQ0^2/Q1+i*deltaB
|
||||
c=-kQ0^2
|
||||
and Q2=(-b+sqrt(b^2+4(1-k)kQ0^2))/2(1-k)
|
||||
note: another root is negative, abondan
|
||||
|
||||
if deltaBSig=true, then Q2>Q1, user sell Q and receive B
|
||||
if deltaBSig=false, then Q2<Q1, user sell B and receive Q
|
||||
return |Q1-Q2|
|
||||
|
||||
as we only support sell amount as delta, the deltaB is always negative
|
||||
the input ideltaB is actually -ideltaB in the equation
|
||||
|
||||
i is the price of delta-V trading pair
|
||||
|
||||
support k=1 & k=0 case
|
||||
|
||||
[round down]
|
||||
*/
|
||||
function _SolveQuadraticFunctionForTrade(
|
||||
uint256 V0,
|
||||
uint256 V1,
|
||||
uint256 delta,
|
||||
uint256 i,
|
||||
uint256 k
|
||||
) internal pure returns (uint256) {
|
||||
require(V0 > 0, "TARGET_IS_ZERO");
|
||||
if (delta == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (k == 0) {
|
||||
// why v1
|
||||
return DecimalMath.mulFloor(i, delta) > V1 ? V1 : DecimalMath.mulFloor(i, delta);
|
||||
}
|
||||
|
||||
if (k == DecimalMath.ONE) {
|
||||
// if k==1
|
||||
// Q2=Q1/(1+ideltaBQ1/Q0/Q0)
|
||||
// temp = ideltaBQ1/Q0/Q0
|
||||
// Q2 = Q1/(1+temp)
|
||||
// Q1-Q2 = Q1*(1-1/(1+temp)) = Q1*(temp/(1+temp))
|
||||
// uint256 temp = i.mul(delta).mul(V1).div(V0.mul(V0));
|
||||
uint256 temp;
|
||||
uint256 idelta = i * (delta);
|
||||
if (idelta == 0) {
|
||||
temp = 0;
|
||||
} else if ((idelta * V1) / idelta == V1) {
|
||||
temp = (idelta * V1) / (V0 * V0);
|
||||
} else {
|
||||
temp = delta * (V1) / (V0) * (i) / (V0);
|
||||
}
|
||||
return V1 * (temp) / (temp + (DecimalMath.ONE));
|
||||
}
|
||||
|
||||
// calculate -b value and sig
|
||||
// b = kQ0^2/Q1-i*deltaB-(1-k)Q1
|
||||
// part1 = (1-k)Q1 >=0
|
||||
// part2 = kQ0^2/Q1-i*deltaB >=0
|
||||
// bAbs = abs(part1-part2)
|
||||
// if part1>part2 => b is negative => bSig is false
|
||||
// if part2>part1 => b is positive => bSig is true
|
||||
uint256 part2 = k * (V0) / (V1) * (V0) + (i * (delta)); // kQ0^2/Q1-i*deltaB
|
||||
uint256 bAbs = (DecimalMath.ONE - k) * (V1); // (1-k)Q1
|
||||
|
||||
bool bSig;
|
||||
if (bAbs >= part2) {
|
||||
bAbs = bAbs - part2;
|
||||
bSig = false;
|
||||
} else {
|
||||
bAbs = part2 - bAbs;
|
||||
bSig = true;
|
||||
}
|
||||
bAbs = bAbs / (DecimalMath.ONE);
|
||||
|
||||
// calculate sqrt
|
||||
uint256 squareRoot = DecimalMath.mulFloor((DecimalMath.ONE - k) * (4), DecimalMath.mulFloor(k, V0) * (V0)); // 4(1-k)kQ0^2
|
||||
squareRoot = Math.sqrt((bAbs * bAbs) + squareRoot); // sqrt(b*b+4(1-k)kQ0*Q0)
|
||||
|
||||
// final res
|
||||
uint256 denominator = (DecimalMath.ONE - k) * 2; // 2(1-k)
|
||||
uint256 numerator;
|
||||
if (bSig) {
|
||||
numerator = squareRoot - bAbs;
|
||||
if (numerator == 0) {
|
||||
revert("DODOMath: should not be 0");
|
||||
}
|
||||
} else {
|
||||
numerator = bAbs + squareRoot;
|
||||
}
|
||||
|
||||
uint256 V2 = DecimalMath.divCeil(numerator, denominator);
|
||||
if (V2 > V1) {
|
||||
return 0;
|
||||
} else {
|
||||
return V1 - V2;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
contracts/DODOGasSavingPool/lib/DecimalMath.sol
Normal file
78
contracts/DODOGasSavingPool/lib/DecimalMath.sol
Normal file
@@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
pragma solidity 0.8.16;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
||||
|
||||
/**
|
||||
* @title DecimalMath
|
||||
* @author DODO Breeder
|
||||
*
|
||||
* @notice Functions for fixed point number with 18 decimals
|
||||
*/
|
||||
|
||||
library DecimalMath {
|
||||
uint256 internal constant ONE = 10 ** 18;
|
||||
uint256 internal constant ONE2 = 10 ** 36;
|
||||
|
||||
function mul(uint256 target, uint256 d) internal pure returns (uint256) {
|
||||
return target * d / (10 ** 18);
|
||||
}
|
||||
|
||||
function mulFloor(uint256 target, uint256 d) internal pure returns (uint256) {
|
||||
return target * d / (10 ** 18);
|
||||
}
|
||||
|
||||
function mulCeil(uint256 target, uint256 d) internal pure returns (uint256) {
|
||||
return _divCeil(target * d, 10 ** 18);
|
||||
}
|
||||
|
||||
function div(uint256 target, uint256 d) internal pure returns (uint256) {
|
||||
return target * (10 ** 18) / d;
|
||||
}
|
||||
|
||||
function divFloor(uint256 target, uint256 d) internal pure returns (uint256) {
|
||||
return target * (10 ** 18) / d;
|
||||
}
|
||||
|
||||
function divCeil(uint256 target, uint256 d) internal pure returns (uint256) {
|
||||
return _divCeil(target * (10 ** 18), d);
|
||||
}
|
||||
|
||||
function reciprocalFloor(uint256 target) internal pure returns (uint256) {
|
||||
return uint256(10 ** 36) / target;
|
||||
}
|
||||
|
||||
function reciprocalCeil(uint256 target) internal pure returns (uint256) {
|
||||
return _divCeil(uint256(10 ** 36), target);
|
||||
}
|
||||
|
||||
function sqrt(uint256 target) internal pure returns (uint256) {
|
||||
return Math.sqrt(target * ONE);
|
||||
}
|
||||
|
||||
function powFloor(uint256 target, uint256 e) internal pure returns (uint256) {
|
||||
if (e == 0) {
|
||||
return 10 ** 18;
|
||||
} else if (e == 1) {
|
||||
return target;
|
||||
} else {
|
||||
uint256 p = powFloor(target, e / 2);
|
||||
p = p * p / (10 ** 18);
|
||||
if (e % 2 == 1) {
|
||||
p = p * target / (10 ** 18);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
function _divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 quotient = a / b;
|
||||
uint256 remainder = a - quotient * b;
|
||||
if (remainder > 0) {
|
||||
return quotient + 1;
|
||||
} else {
|
||||
return quotient;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
contracts/DODOGasSavingPool/lib/InitializableOwnable.sol
Normal file
58
contracts/DODOGasSavingPool/lib/InitializableOwnable.sol
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.8.16;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Ownable
|
||||
* @author DODO Breeder
|
||||
*
|
||||
* @notice Ownership related functions
|
||||
*/
|
||||
contract InitializableOwnable {
|
||||
address public _OWNER_;
|
||||
address public _NEW_OWNER_;
|
||||
bool internal _INITIALIZED_;
|
||||
|
||||
// ============ Events ============
|
||||
|
||||
event OwnershipTransferPrepared(address indexed previousOwner, address indexed newOwner);
|
||||
|
||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||
|
||||
// ============ Modifiers ============
|
||||
|
||||
modifier notInitialized() {
|
||||
require(!_INITIALIZED_, "DODO_INITIALIZED");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == _OWNER_, "NOT_OWNER");
|
||||
_;
|
||||
}
|
||||
|
||||
// ============ Functions ============
|
||||
|
||||
function initOwner(address newOwner) public notInitialized {
|
||||
_INITIALIZED_ = true;
|
||||
_OWNER_ = newOwner;
|
||||
}
|
||||
|
||||
function transferOwnership(address newOwner) public onlyOwner {
|
||||
emit OwnershipTransferPrepared(_OWNER_, newOwner);
|
||||
_NEW_OWNER_ = newOwner;
|
||||
}
|
||||
|
||||
function claimOwnership() public {
|
||||
require(msg.sender == _NEW_OWNER_, "INVALID_CLAIM");
|
||||
emit OwnershipTransferred(_OWNER_, _NEW_OWNER_);
|
||||
_OWNER_ = _NEW_OWNER_;
|
||||
_NEW_OWNER_ = address(0);
|
||||
}
|
||||
}
|
||||
266
contracts/DODOGasSavingPool/lib/PMMPricing.sol
Normal file
266
contracts/DODOGasSavingPool/lib/PMMPricing.sol
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.8.16;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {DecimalMath} from "../lib/DecimalMath.sol";
|
||||
import {DODOMath} from "../lib/DODOMath.sol";
|
||||
|
||||
/**
|
||||
* @title Pricing
|
||||
* @author DODO Breeder
|
||||
*
|
||||
* @notice DODO Pricing model
|
||||
*/
|
||||
|
||||
library PMMPricing {
|
||||
|
||||
enum RState {ONE, ABOVE_ONE, BELOW_ONE}
|
||||
|
||||
struct PMMState {
|
||||
uint256 i;
|
||||
uint256 K;
|
||||
uint256 B;
|
||||
uint256 Q;
|
||||
uint256 B0;
|
||||
uint256 Q0;
|
||||
RState R;
|
||||
}
|
||||
|
||||
// ============ buy & sell ============
|
||||
/**
|
||||
* @notice Inner calculation based on pmm algorithm, sell base
|
||||
* @param state The current PMM state
|
||||
* @param payBaseAmount The amount of base token user want to sell
|
||||
* @return receiveQuoteAmount The amount of quote token user will receive
|
||||
* @return newR The new R status after swap
|
||||
*/
|
||||
function sellBaseToken(PMMState memory state, uint256 payBaseAmount)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 receiveQuoteAmount, RState newR)
|
||||
{
|
||||
if (state.R == RState.ONE) {
|
||||
// case 1: R=1
|
||||
// R falls below one
|
||||
receiveQuoteAmount = _ROneSellBaseToken(state, payBaseAmount);
|
||||
newR = RState.BELOW_ONE;
|
||||
} else if (state.R == RState.ABOVE_ONE) {
|
||||
uint256 backToOnePayBase = state.B0 - state.B;
|
||||
uint256 backToOneReceiveQuote = state.Q - state.Q0;
|
||||
// case 2: R>1
|
||||
// complex case, R status depends on trading amount
|
||||
if (payBaseAmount < backToOnePayBase) {
|
||||
// case 2.1: R status do not change
|
||||
receiveQuoteAmount = _RAboveSellBaseToken(state, payBaseAmount);
|
||||
newR = RState.ABOVE_ONE;
|
||||
if (receiveQuoteAmount > backToOneReceiveQuote) {
|
||||
// [Important corner case!] may enter this branch when some precision problem happens. And consequently contribute to negative spare quote amount
|
||||
// to make sure spare quote>=0, mannually set receiveQuote=backToOneReceiveQuote
|
||||
receiveQuoteAmount = backToOneReceiveQuote;
|
||||
}
|
||||
} else if (payBaseAmount == backToOnePayBase) {
|
||||
// case 2.2: R status changes to ONE
|
||||
receiveQuoteAmount = backToOneReceiveQuote;
|
||||
newR = RState.ONE;
|
||||
} else {
|
||||
// case 2.3: R status changes to BELOW_ONE
|
||||
receiveQuoteAmount = backToOneReceiveQuote + (
|
||||
_ROneSellBaseToken(state, (payBaseAmount - backToOnePayBase))
|
||||
);
|
||||
newR = RState.BELOW_ONE;
|
||||
}
|
||||
} else {
|
||||
// state.R == RState.BELOW_ONE
|
||||
// case 3: R<1
|
||||
receiveQuoteAmount = _RBelowSellBaseToken(state, payBaseAmount);
|
||||
newR = RState.BELOW_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Inner calculation based on pmm algorithm, sell quote
|
||||
* @param state The current PMM state
|
||||
* @param payQuoteAmount The amount of quote token user want to sell
|
||||
* @return receiveBaseAmount The amount of base token user will receive
|
||||
* @return newR The new R status after swap
|
||||
*/
|
||||
function sellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 receiveBaseAmount, RState newR)
|
||||
{
|
||||
if (state.R == RState.ONE) {
|
||||
receiveBaseAmount = _ROneSellQuoteToken(state, payQuoteAmount);
|
||||
newR = RState.ABOVE_ONE;
|
||||
} else if (state.R == RState.ABOVE_ONE) {
|
||||
receiveBaseAmount = _RAboveSellQuoteToken(state, payQuoteAmount);
|
||||
newR = RState.ABOVE_ONE;
|
||||
} else {
|
||||
uint256 backToOnePayQuote = state.Q0 - state.Q;
|
||||
uint256 backToOneReceiveBase = state.B - state.B0;
|
||||
if (payQuoteAmount < backToOnePayQuote) {
|
||||
receiveBaseAmount = _RBelowSellQuoteToken(state, payQuoteAmount);
|
||||
newR = RState.BELOW_ONE;
|
||||
if (receiveBaseAmount > backToOneReceiveBase) {
|
||||
receiveBaseAmount = backToOneReceiveBase;
|
||||
}
|
||||
} else if (payQuoteAmount == backToOnePayQuote) {
|
||||
receiveBaseAmount = backToOneReceiveBase;
|
||||
newR = RState.ONE;
|
||||
} else {
|
||||
receiveBaseAmount = backToOneReceiveBase + (
|
||||
_ROneSellQuoteToken(state, payQuoteAmount - backToOnePayQuote)
|
||||
);
|
||||
newR = RState.ABOVE_ONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============ R = 1 cases ============
|
||||
|
||||
function _ROneSellBaseToken(PMMState memory state, uint256 payBaseAmount)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 // receiveQuoteToken
|
||||
)
|
||||
{
|
||||
// in theory Q2 <= targetQuoteTokenAmount
|
||||
// however when amount is close to 0, precision problems may cause Q2 > targetQuoteTokenAmount
|
||||
return
|
||||
DODOMath._SolveQuadraticFunctionForTrade(
|
||||
state.Q0,
|
||||
state.Q0,
|
||||
payBaseAmount,
|
||||
state.i,
|
||||
state.K
|
||||
);
|
||||
}
|
||||
|
||||
function _ROneSellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 // receiveBaseToken
|
||||
)
|
||||
{
|
||||
return
|
||||
DODOMath._SolveQuadraticFunctionForTrade(
|
||||
state.B0,
|
||||
state.B0,
|
||||
payQuoteAmount,
|
||||
DecimalMath.reciprocalFloor(state.i),
|
||||
state.K
|
||||
);
|
||||
}
|
||||
|
||||
// ============ R < 1 cases ============
|
||||
|
||||
function _RBelowSellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 // receiveBaseToken
|
||||
)
|
||||
{
|
||||
return
|
||||
DODOMath._GeneralIntegrate(
|
||||
state.Q0,
|
||||
state.Q + payQuoteAmount,
|
||||
state.Q,
|
||||
DecimalMath.reciprocalFloor(state.i),
|
||||
state.K
|
||||
);
|
||||
}
|
||||
|
||||
function _RBelowSellBaseToken(PMMState memory state, uint256 payBaseAmount)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 // receiveQuoteToken
|
||||
)
|
||||
{
|
||||
return
|
||||
DODOMath._SolveQuadraticFunctionForTrade(
|
||||
state.Q0,
|
||||
state.Q,
|
||||
payBaseAmount,
|
||||
state.i,
|
||||
state.K
|
||||
);
|
||||
}
|
||||
|
||||
// ============ R > 1 cases ============
|
||||
|
||||
function _RAboveSellBaseToken(PMMState memory state, uint256 payBaseAmount)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 // receiveQuoteToken
|
||||
)
|
||||
{
|
||||
return
|
||||
DODOMath._GeneralIntegrate(
|
||||
state.B0,
|
||||
state.B + payBaseAmount,
|
||||
state.B,
|
||||
state.i,
|
||||
state.K
|
||||
);
|
||||
}
|
||||
|
||||
function _RAboveSellQuoteToken(PMMState memory state, uint256 payQuoteAmount)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 // receiveBaseToken
|
||||
)
|
||||
{
|
||||
return
|
||||
DODOMath._SolveQuadraticFunctionForTrade(
|
||||
state.B0,
|
||||
state.B,
|
||||
payQuoteAmount,
|
||||
DecimalMath.reciprocalFloor(state.i),
|
||||
state.K
|
||||
);
|
||||
}
|
||||
|
||||
// ============ Helper functions ============
|
||||
|
||||
function adjustedTarget(PMMState memory state) internal pure {
|
||||
if (state.R == RState.BELOW_ONE) {
|
||||
state.Q0 = DODOMath._SolveQuadraticFunctionForTarget(
|
||||
state.Q,
|
||||
state.B - state.B0,
|
||||
state.i,
|
||||
state.K
|
||||
);
|
||||
} else if (state.R == RState.ABOVE_ONE) {
|
||||
state.B0 = DODOMath._SolveQuadraticFunctionForTarget(
|
||||
state.B,
|
||||
state.Q - state.Q0,
|
||||
DecimalMath.reciprocalFloor(state.i),
|
||||
state.K
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getMidPrice(PMMState memory state) internal pure returns (uint256) {
|
||||
if (state.R == RState.BELOW_ONE) {
|
||||
uint256 R = DecimalMath.divFloor(state.Q0 * state.Q0 / state.Q, state.Q);
|
||||
R = DecimalMath.ONE - state.K + (DecimalMath.mulFloor(state.K, R));
|
||||
return DecimalMath.divFloor(state.i, R);
|
||||
} else {
|
||||
uint256 R = DecimalMath.divFloor(state.B0 * state.B0 / state.B, state.B);
|
||||
R = DecimalMath.ONE - state.K + (DecimalMath.mulFloor(state.K, R));
|
||||
return DecimalMath.mulFloor(state.i, R);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user