Files
dodo-contractV2/contracts/lib/DODOMath.sol
2020-06-26 00:31:25 +08:00

118 lines
3.7 KiB
Solidity

/*
Copyright 2020 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
import {SafeMath} from "./SafeMath.sol";
import {DecimalMath} from "./DecimalMath.sol";
/**
* @title DODOMath
* @author DODO Breeder
*
* @notice Functions for complex calculating. Including ONE Integration and TWO Quadratic solutions
*/
library DODOMath {
using SafeMath for uint256;
/*
Integrate dodo curve fron 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))
*/
function _GeneralIntegrate(
uint256 V0,
uint256 V1,
uint256 V2,
uint256 i,
uint256 k
) internal pure returns (uint256) {
uint256 fairAmount = DecimalMath.mul(i, V1.sub(V2)); // i*delta
uint256 V0V1 = DecimalMath.divCeil(V0, V1); // V0/V1
uint256 V0V2 = DecimalMath.divCeil(V0, V2); // V0/V2
uint256 penalty = DecimalMath.mul(DecimalMath.mul(k, V0V1), V0V2); // k(V0^2/V1/V2)
return DecimalMath.mul(fairAmount, DecimalMath.ONE.sub(k).add(penalty));
}
/*
The same with 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
if deltaBSig=false, then Q2<Q1
*/
function _SolveQuadraticFunctionForTrade(
uint256 Q0,
uint256 Q1,
uint256 ideltaB,
bool deltaBSig,
uint256 k
) internal pure returns (uint256) {
// calculate -b value and sig
// -b = (1-k)Q1-kQ0^2/Q1+i*deltaB
uint256 kQ02Q1 = DecimalMath.mul(k, Q0).mul(Q0).div(Q1); // kQ0^2/Q1
uint256 b = DecimalMath.mul(DecimalMath.ONE.sub(k), Q1); // (1-k)Q1
bool minusbSig = true;
if (deltaBSig) {
b = b.add(ideltaB); // (1-k)Q1+i*deltaB
} else {
kQ02Q1 = kQ02Q1.add(ideltaB); // -i*(-deltaB)-kQ0^2/Q1
}
if (b >= kQ02Q1) {
b = b.sub(kQ02Q1);
minusbSig = true;
} else {
b = kQ02Q1.sub(b);
minusbSig = false;
}
// calculate sqrt
uint256 squareRoot = DecimalMath.mul(
DecimalMath.ONE.sub(k).mul(4),
DecimalMath.mul(k, Q0).mul(Q0)
); // 4(1-k)kQ0^2
squareRoot = b.mul(b).add(squareRoot).sqrt(); // sqrt(b*b-4(1-k)kQ0*Q0)
// final res
uint256 denominator = DecimalMath.ONE.sub(k).mul(2); // 2(1-k)
if (minusbSig) {
return DecimalMath.divFloor(b.add(squareRoot), denominator);
} else {
return DecimalMath.divFloor(squareRoot.sub(b), denominator);
}
}
/*
Start from the integration function
i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2)
Assume Q2=Q0, Given Q1 and deltaB, solve Q0
let fairAmount = i*deltaB
*/
function _SolveQuadraticFunctionForTarget(
uint256 V1,
uint256 k,
uint256 fairAmount
) internal pure returns (uint256 V0) {
// V0 = V1+V1*(sqrt-1)/2k
uint256 sqrt = DecimalMath.divFloor(DecimalMath.mul(k, fairAmount), V1).mul(4);
sqrt = sqrt.add(DecimalMath.ONE).mul(DecimalMath.ONE).sqrt();
uint256 premium = DecimalMath.divFloor(sqrt.sub(DecimalMath.ONE), k.mul(2));
// V0 is greater than or equal to V1 according to the solution
return DecimalMath.mul(V1, DecimalMath.ONE.add(premium));
}
}