BMath.sol

Created Diff never expires
25 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
272 lines
46 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
299 lines
// This program is free software: you can redistribute it and/or modify
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// (at your option) any later version.


// This program is distributed in the hope that it will be useful,
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// GNU General Public License for more details.


// You should have received a copy of the GNU General Public License
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// along with this program. If not, see <http://www.gnu.org/licenses/>.


pragma solidity 0.5.12;
pragma solidity 0.5.12;


import "./BNum.sol";
import "./BNum.sol";


contract BMath is BBronze, BConst, BNum {
contract BMath is BBronze, BConst, BNum {
/**********************************************************************************************
/**********************************************************************************************
// calcSpotPrice //
// calcSpotPrice //
// sP = spotPrice //
// sP = spotPrice //
// bI = tokenBalanceIn ( bI / wI ) 1 //
// bI = tokenBalanceIn ( bI / wI ) 1 //
// bO = tokenBalanceOut sP = ----------- * ---------- //
// bO = tokenBalanceOut sP = ----------- * ---------- //
// wI = tokenWeightIn ( bO / wO ) ( 1 - sF ) //
// wI = tokenWeightIn ( bO / wO ) ( 1 - sF ) //
// wO = tokenWeightOut //
// wO = tokenWeightOut //
// sF = swapFee //
// sF = swapFee //
**********************************************************************************************/
**********************************************************************************************/
function calcSpotPrice(
function calcSpotPrice(
uint tokenBalanceIn,
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenWeightOut,
uint swapFee
uint swapFee
)
)
public pure
public pure
returns (uint spotPrice)
returns (uint spotPrice)
{
{
uint numer = bdiv(tokenBalanceIn, tokenWeightIn);
uint numer = bdiv(tokenBalanceIn, tokenWeightIn);
uint denom = bdiv(tokenBalanceOut, tokenWeightOut);
uint denom = bdiv(tokenBalanceOut, tokenWeightOut);
uint ratio = bdiv(numer, denom);
uint ratio = bdiv(numer, denom);
uint scale = bdiv(BONE, bsub(BONE, swapFee));
uint scale = bdiv(BONE, bsub(BONE, swapFee));
return (spotPrice = bmul(ratio, scale));
return (spotPrice = bmul(ratio, scale));
}
}


/**********************************************************************************************
/**********************************************************************************************
// calcOutGivenIn //
// calcOutGivenIn //
// aO = tokenAmountOut //
// aO = tokenAmountOut //
// bO = tokenBalanceOut //
// bO = tokenBalanceOut //
// bI = tokenBalanceIn / / bI \ (wI / wO) \ //
// bI = tokenBalanceIn / / bI \ (wI / wO) \ //
// aI = tokenAmountIn aO = bO * | 1 - | -------------------------- | ^ | //
// aI = tokenAmountIn aO = bO * | 1 - | -------------------------- | ^ | //
// wI = tokenWeightIn \ \ ( bI + ( aI * ( 1 - sF )) / / //
// wI = tokenWeightIn \ \ ( bI + ( aI * ( 1 - sF )) / / //
// wO = tokenWeightOut //
// wO = tokenWeightOut //
// sF = swapFee //
// sF = swapFee //
**********************************************************************************************/
**********************************************************************************************/
function calcOutGivenIn(
function calcOutGivenIn(
uint tokenBalanceIn,
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenWeightOut,
uint tokenAmountIn,
uint tokenAmountIn,
uint swapFee
uint swapFee
)
)
public pure
public pure
returns (uint tokenAmountOut)
returns (uint tokenAmountOut, uint tokenInFee)
{
{
uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
uint adjustedIn = bsub(BONE, swapFee);
uint adjustedIn = bsub(BONE, swapFee);
adjustedIn = bmul(tokenAmountIn, adjustedIn);
adjustedIn = bmul(tokenAmountIn, adjustedIn);
uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
uint foo = bpow(y, weightRatio);
uint foo = bpow(y, weightRatio);
uint bar = bsub(BONE, foo);
uint bar = bsub(BONE, foo);
tokenAmountOut = bmul(tokenBalanceOut, bar);
tokenAmountOut = bmul(tokenBalanceOut, bar);
return tokenAmountOut;
tokenInFee = bsub(tokenAmountIn, adjustedIn);
return (tokenAmountOut, tokenInFee);
}
}


/**********************************************************************************************
/**********************************************************************************************
// calcInGivenOut //
// calcInGivenOut //
// aI = tokenAmountIn //
// aI = tokenAmountIn //
// bO = tokenBalanceOut / / bO \ (wO / wI) \ //
// bO = tokenBalanceOut / / bO \ (wO / wI) \ //
// bI = tokenBalanceIn bI * | | ------------ | ^ - 1 | //
// bI = tokenBalanceIn bI * | | ------------ | ^ - 1 | //
// aO = tokenAmountOut aI = \ \ ( bO - aO ) / / //
// aO = tokenAmountOut aI = \ \ ( bO - aO ) / / //
// wI = tokenWeightIn -------------------------------------------- //
// wI = tokenWeightIn -------------------------------------------- //
// wO = tokenWeightOut ( 1 - sF ) //
// wO = tokenWeightOut ( 1 - sF ) //
// sF = swapFee //
// sF = swapFee //
**********************************************************************************************/
**********************************************************************************************/
function calcInGivenOut(
function calcInGivenOut(
uint tokenBalanceIn,
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenWeightOut,
uint tokenAmountOut,
uint tokenAmountOut,
uint swapFee
uint swapFee
)
)
public pure
public pure
returns (uint tokenAmountIn)
returns (uint tokenAmountIn, uint tokenInFee)
{
{
uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
uint diff = bsub(tokenBalanceOut, tokenAmountOut);
uint diff = bsub(tokenBalanceOut, tokenAmountOut);
uint y = bdiv(tokenBalanceOut, diff);
uint y = bdiv(tokenBalanceOut, diff);
uint foo = bpow(y, weightRatio);
uint foo = bpow(y, weightRatio);
foo = bsub(foo, BONE);
foo = bsub(foo, BONE);
foo = bmul(tokenBalanceIn, foo);
tokenAmountIn = bsub(BONE, swapFee);
tokenAmountIn = bsub(BONE, swapFee);
tokenAmountIn = bdiv(bmul(tokenBalanceIn, foo), tokenAmountIn);
tokenAmountIn = bdiv(foo, tokenAmountIn);
return tokenAmountIn;
tokenInFee = bdiv(foo, BONE);
tokenInFee = bsub(tokenAmountIn, tokenInFee);
return (tokenAmountIn, tokenInFee);
}
}


/**********************************************************************************************
/**********************************************************************************************
// calcPoolOutGivenSingleIn //
// calcPoolOutGivenSingleIn //
// pAo = poolAmountOut / \ //
// pAo = poolAmountOut / \ //
// tAi = tokenAmountIn /// / // wI \ \\ \ wI \ //
// tAi = tokenAmountIn /// / // wI \ \\ \ wI \ //
// wI = tokenWeightIn //| tAi *| 1 - || 1 - -- | * sF || + tBi \ -- \ //
// wI = tokenWeightIn //| tAi *| 1 - || 1 - -- | * sF || + tBi \ -- \ //
// tW = totalWeight pAo=|| \ \ \\ tW / // | ^ tW | * pS - pS //
// tW = totalWeight pAo=|| \ \ \\ tW / // | ^ tW | * pS - pS //
// tBi = tokenBalanceIn \\ ------------------------------------- / / //
// tBi = tokenBalanceIn \\ ------------------------------------- / / //
// pS = poolSupply \\ tBi / / //
// pS = poolSupply \\ tBi / / //
// sF = swapFee \ / //
// sF = swapFee \ / //
**********************************************************************************************/
**********************************************************************************************/
function calcPoolOutGivenSingleIn(
function calcPoolOutGivenSingleIn(
uint tokenBalanceIn,
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenWeightIn,
uint poolSupply,
uint poolSupply,
uint totalWeight,
uint totalWeight,
uint tokenAmountIn,
uint tokenAmountIn,
uint swapFee
uint swapFee,
uint reservesRatio
)
)
public pure
public pure
returns (uint poolAmountOut)
returns (uint poolAmountOut, uint reserves)
{
{
// Charge the trading fee for the proportion of tokenAi
// Charge the trading fee for the proportion of tokenAi
/// which is implicitly traded to the other pool tokens.
/// which is implicitly traded to the other pool tokens.
// That proportion is (1- weightTokenIn)
// That proportion is (1- weightTokenIn)
// tokenAiAfterFee = tAi * (1 - (1-weightTi) * poolFee);
// tokenAiAfterFee = tAi * (1 - (1-weightTi) * poolFee);
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
// Exact fee portion of `tokenAmountIn`, i.e. (1- Wt)
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BONE, zaz));
uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BONE, zaz));


reserves = calcReserves(tokenAmountIn, tokenAmountInAfterFee, reservesRatio);
uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);
uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);
uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);
uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);


// uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;
// uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;
uint poolRatio = bpow(tokenInRatio, normalizedWeight);
uint poolRatio = bpow(tokenInRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
uint newPoolSupply = bmul(poolRatio, poolSupply);
poolAmountOut = bsub(newPoolSupply, poolSupply);
poolAmountOut = bsub(newPoolSupply, poolSupply);
return poolAmountOut;
return (poolAmountOut, reserves);
}
}


/**********************************************************************************************
/**********************************************************************************************
// calcSingleInGivenPoolOut //
// calcSingleInGivenPoolOut //
// tAi = tokenAmountIn //(pS + pAo)\ / 1 \\ //
// tAi = tokenAmountIn //(pS + pAo)\ / 1 \\ //
// pS = poolSupply || --------- | ^ | --------- || * bI - bI //
// pS = poolSupply || --------- | ^ | --------- || * bI - bI //
// pAo = poolAmountOut \\ pS / \(wI / tW)// //
// pAo = poolAmountOut \\ pS / \(wI / tW)// //
// bI = balanceIn tAi = -------------------------------------------- //
// bI = balanceIn tAi = -------------------------------------------- //
// wI = weightIn / wI \ //
// wI = weightIn / wI \ //
// tW = totalWeight | 1 - ---- | * sF //
// tW = totalWeight | 1 - ---- | * sF //
// sF = swapFee \ tW / //
// sF = swapFee \ tW / //
**********************************************************************************************/
**********************************************************************************************/
function calcSingleInGivenPoolOut(
function calcSingleInGivenPoolOut(
uint tokenBalanceIn,
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenWeightIn,
uint poolSupply,
uint poolSupply,
uint totalWeight,
uint totalWeight,
uint poolAmountOut,
uint poolAmountOut,
uint swapFee
uint swapFee
)
)
public pure
public pure
returns (uint tokenAmountIn)
returns (uint tokenAmountIn)
{
{
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint newPoolSupply = badd(poolSupply, poolAmountOut);
uint newPoolSupply = badd(poolSupply, poolAmountOut);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
uint poolRatio = bdiv(newPoolSupply, poolSupply);

//uint newBalTi = poolRatio^(1/weightTi) * balTi;
//uint newBalTi = poolRatio^(1/weightTi) * balTi;
uint boo = bdiv(BONE, normalizedWeight);
uint boo = bdiv(BONE, normalizedWeight);
uint tokenInRatio = bpow(poolRatio, boo);
uint tokenInRatio = bpow(poolRatio, boo);
uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn);
uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn);
uint tokenAmountInAfterFee = bsub(newTokenBalanceIn, tokenBalanceIn);
uint tokenAmountInAfterFee = bsub(newTokenBalanceIn, tokenBalanceIn);
// Do reverse order of fees charged in joinswap_ExternAmountIn, this way
// Do reverse order of fees charged in joinswap_ExternAmountIn, this way
// ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```
// ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```
//uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;
//uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;
uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);
uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);
tokenAmountIn = bdiv(tokenAmountInAfterFee, bsub(BONE, zar));
tokenAmountIn = bdiv(tokenAmountInAfterFee, bsub(BONE, zar));
return tokenAmountIn;
return tokenAmountIn;
}
}


/**********************************************************************************************
/**********************************************************************************************
// calcSingleOutGivenPoolIn //
// calcSingleOutGivenPoolIn //
// tAo = tokenAmountOut / / \\ //
// tAo = tokenAmountOut / / \\ //
// bO = tokenBalanceOut / // pS - (pAi * (1 - eF)) \ / 1 \ \\ //
// bO = tokenBalanceOut / // pS - (pAi * (1 - eF)) \ / 1 \ \\ //
// pAi = poolAmountIn | bO - || ----------------------- | ^ | --------- | * b0 || //
// pAi = poolAmountIn | bO - || ----------------------- | ^ | --------- | * b0 || //
// ps = poolSupply \ \\ pS / \(wO / tW)/ // //
// ps = poolSupply \ \\ pS / \(wO / tW)/ // //
// wI = tokenWeightIn tAo = \ \ // //
// wI = tokenWeightIn tAo = \ \ // //
// tW = totalWeight / / wO \ \ //
// tW = totalWeight / / wO \ \ //
// sF = swapFee * | 1 - | 1 - ---- | * sF | //
// sF = swapFee * | 1 - | 1 - ---- | * sF | //
// eF = exitFee \ \ tW / / //
// eF = exitFee \ \ tW / / //
**********************************************************************************************/
**********************************************************************************************/
function calcSingleOutGivenPoolIn(
function calcSingleOutGivenPoolIn(
uint tokenBalanceOut,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenWeightOut,
uint poolSupply,
uint poolSupply,
uint totalWeight,
uint totalWeight,
uint poolAmountIn,
uint poolAmountIn,
uint swapFee
uint swapFee
)
)
public pure
public pure
returns (uint tokenAmountOut)
returns (uint tokenAmountOut)
{
{
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
// charge exit fee on the pool token side
// charge exit fee on the pool token side
// pAiAfterExitFee = pAi*(1-exitFee)
// pAiAfterExitFee = pAi*(1-exitFee)
uint poolAmountInAfterExitFee = bmul(poolAmountIn, bsub(BONE, EXIT_FEE));
uint poolAmountInAfterExitFee = bmul(poolAmountIn, bsub(BONE, EXIT_FEE));
uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);
uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
uint poolRatio = bdiv(newPoolSupply, poolSupply);

// newBalTo = poolRatio^(1/weightTo) * balTo;
// newBalTo = poolRatio^(1/weightTo) * balTo;
uint tokenOutRatio = bpow(poolRatio, bdiv(BONE, normalizedWeight));
uint tokenOutRatio = bpow(poolRatio, bdiv(BONE, normalizedWeight));
uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);
uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);


uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);
uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);


// charge swap fee on the output token side
// charge swap fee on the output token side
//uint tAo = tAoBeforeSwapFee * (1 - (1-weightTo) * swapFee)
//uint tAo = tAoBeforeSwapFee * (1 - (1-weightTo) * swapFee)
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BONE, zaz));
tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BONE, zaz));
return tokenAmountOut;
return tokenAmountOut;
}
}


/**********************************************************************************************
/**********************************************************************************************
// calcPoolInGivenSingleOut //
// calcPoolInGivenSingleOut //
// pAi = poolAmountIn // / tAo \\ / wO \ \ //
// pAi = poolAmountIn // / tAo \\ / wO \ \ //
// bO = tokenBalanceOut // | bO - -------------------------- |\ | ---- | \ //
// bO = tokenBalanceOut // | bO - -------------------------- |\ | ---- | \ //
// tAo = tokenAmountOut pS - || \ 1 - ((1 - (tO / tW)) * sF)/ | ^ \ tW / * pS | //
// tAo = tokenAmountOut pS - || \ 1 - ((1 - (tO / tW)) * sF)/ | ^ \ tW / * pS | //
// ps = poolSupply \\ -----------------------------------/ / //
// ps = poolSupply \\ -----------------------------------/ / //
// wO = tokenWeightOut pAi = \\ bO / / //
// wO = tokenWeightOut pAi = \\ bO / / //
// tW = totalWeight ------------------------------------------------------------- //
// tW = totalWeight ------------------------------------------------------------- //
// sF = swapFee ( 1 - eF ) //
// sF = swapFee ( 1 - eF ) //
// eF = exitFee //
// eF = exitFee //
**********************************************************************************************/
**********************************************************************************************/
function calcPoolInGivenSingleOut(
function calcPoolInGivenSingleOut(
uint tokenBalanceOut,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenWeightOut,
uint poolSupply,
uint poolSupply,
uint totalWeight,
uint totalWeight,
uint tokenAmountOut,
uint tokenAmountOut,
uint swapFee
uint swapFee,
uint reservesRatio
)
)
public pure
public pure
returns (uint poolAmountIn)
returns (uint poolAmountIn, uint reserves)
{
{


// charge swap fee on the output token side
// charge swap fee on the output token side
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
//uint tAoBeforeSwapFee = tAo / (1 - (1-weightTo) * swapFee) ;
uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);
uint zoo = bsub(BONE, normalizedWeight);
uint zar = bmul(zoo, swapFee);
uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BONE, zar));
uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BONE, zar));
reserves = calcReserves(tokenAmountOutBeforeSwapFee, tokenAmountOut, reservesRatio);


uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);
uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);
uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);
uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);


//uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;
//uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;
uint poolRatio = bpow(tokenOutRatio, normalizedWeight);
uint poolRatio = bpow(tokenOutRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
uint newPoolSupply = bmul(poolRatio, poolSupply);
uint poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);
uint poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);


// charge exit fee on the pool token side
// charge exit fee on the pool token side
// pAi = pAiAfterExitFee/(1-exitFee)
// pAi = pAiAfterExitFee/(1-exitFee)
poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BONE, EXIT_FEE));
poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BONE, EXIT_FEE));
return poolAmountIn;
return (poolAmountIn, reserves);
}
}


// `swapFeeAndReserves = amountWithFee - amountWithoutFee` is the swap fee in balancer.
// We divide `swapFeeAndReserves` into halves, `actualSwapFee` and `reserves`.
// `reserves` goes to the admin and `actualSwapFee` still goes to the liquidity
// providers.
function calcReserves(uint amountWithFee, uint amountWithoutFee, uint reservesRatio)
internal pure
returns (uint reserves)
{
require(amountWithFee >= amountWithoutFee, "ERR_MATH_APPROX");
require(reservesRatio <= BONE, "ERR_INVALID_RESERVE");
uint swapFeeAndReserves = bsub(amountWithFee, amountWithoutFee);
reserves = bmul(swapFeeAndReserves, reservesRatio);
require(swapFeeAndReserves >= reserves, "ERR_MATH_APPROX");
}


function calcReservesFromFee(uint fee, uint reservesRatio)
internal pure
returns (uint reserves)
{
require(reservesRatio <= BONE, "ERR_INVALID_RESERVE");
reserves = bmul(fee, reservesRatio);
}
}
}