BancorFormula
Author: Bancor
This contract provides functions for calculating the purchase and sale return values on an exponential curve using a reserve ratio. The formula converts a given reserve token amount into a token return and the sale of a token amount into a reserve token return.
This is an updated version of the BancorFormula contract from the Bancor Protocol. Editted to be compatible with Solidity 0.8.28. See README.md for detailed changes.
State Variables
MIN_PRECISION
Minimum precision index in the maxExpArray
MAX_PRECISION
Maximum precision index in the maxExpArray
MAX_RATIO
Max reserve ratio in parts per million
ONE
Constant variable for 1
FIXED_1
Represents 2 to the power of 127 or 1.7014e38
FIXED_2
Represents 2 to the power of 128 or 3.4028e38
MAX_NUM
Represents 2 to the power of 129 or 6.8056e38
LN2_NUMERATOR
Numerator used to convert from base 2 to natural logarithm
LN2_DENOMINATOR
Denominator used to convert from base 2 to natural logarithm
OPT_LOG_MAX_VAL
Max value at which the _optimalLog function approximations are still effective
OPT_EXP_MAX_VAL
Max value at which the _optimalExp function approximations are still effective
maxExpArray
The array of values used to find the precision needed for the given input
Functions
constructor
Since maxExpArray is a fixed-size array, we need to initialize it in the constructor. To expand the array at the cost of higher gas fees, uncomment the following lines.
_calculateBancorFormulaPurchaseReturn
Returns the purchase value for a given amount (in the reserve token) as a conversion into the main token.
Formula: Return = supply * ((1 + depositAmount / reserveBalance) ^ (reserveRatio / 1000000) - 1)
Parameters
supply
uint256
token total supply
reserveBalance
uint256
balance of reserve token
reserveRatio
uint32
reserve ratio, represented in ppm, 1-1000000
depositAmount
uint256
deposit amount, in reserve token
Returns
purchaseReturn
uint256
return of the conversion
_calculateBancorFormulaSaleReturn
Returns the sale value for a given amount (in the main token) as a conversion into the reserve token.
Formula: Return = reserveBalance * (1 - (1 - sellAmount / supply) ^ (1 / (reserveRatio / 1000000)))
Parameters
supply
uint256
token total supply
reserveBalance
uint256
total reserve
reserveRatio
uint32
reserve ratio, represented in ppm, 1-1000000
sellAmount
uint256
amount of tokens to sell
Returns
saleReturn
uint256
return of the conversion
_power
Returns the exponentiation result along with the precision used.
Detailed Description:
Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)".
The value of "log(base)" is represented with an integer slightly smaller than "log(base) * 2 ^ precision".
The larger "precision" is, the more accurately this value represents the real value.
However, the larger "precision" is, the more bits are required in order to store this value.
And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (maximum value of "x").
This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function.
This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations.
This functions assumes that "expN < 2 ^ 256 / log(MAX_NUM - 1)"
Parameters
baseN
uint256
base numerator
baseD
uint256
base denominator
expN
uint32
exponent numerator
expD
uint32
exponent denominator
Returns
result
uint256
exponentiation result
precision
uint8
precision used
_findPositionInMaxExpArray
The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent:
Returns the position of [the smallest value in "maxExpArray" larger than or equal to "x"].
Returns the highest position of [a value in "maxExpArray" larger than or equal to "x"].
Parameters
x
uint256
input
Returns
position
uint8
position of the value in the array
_generalLog
Returns the logarithm of a given input.
This functions assumes that "x >= FIXED_1", because the output would be negative otherwise.
Parameters
x
uint256
input
Returns
result
uint256
logarithm of x
_floorLog2
Returns the largest integer smaller than or equal to the binary logarithm of the input.
Parameters
x
uint256
input
Returns
result
uint8
result
_generalExp
Returns the exponentiation of a given input.
It approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!".
It returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy.
The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1".
The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
Parameters
x
uint256
input
precision
uint8
precision
Returns
result
uint256
result
_optimalLog
Returns the logarithm of a given input.
Returns log(x / FIXED_1) * FIXED_1. Input range: FIXED_1 <= x <= OPT_LOG_MAX_VAL - 1.
*Detailed description:
Rewrite the input as a product of natural exponents and a single residual r, such that 1 < r < 2.
The natural logarithm of each (pre-calculated) exponent is the degree of the exponent.
The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1.
The natural logarithm of the input is calculated by summing up the intermediate results above.
For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859).*
Parameters
x
uint256
input
Returns
result
uint256
result
_optimalExp
Returns the exponentiation of a given input.
Return e ^ (x / FIXED_1) * FIXED_1. Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1.
*Detailed description:
Rewrite the input as a sum of binary exponents and a single residual r, as small as possible.
The exponentiation of each binary exponent is given (pre-calculated).
The exponentiation of r is calculated via Taylor series for e^x, where x = r.
The exponentiation of the input is calculated by multiplying the intermediate results above.
For example: e^5.021692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859.*
Parameters
x
uint256
input
Returns
result
uint256
result
Errors
BancorFormula__InvalidInput
Last updated