Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Math Refactor #740

Merged
merged 7 commits into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 95 additions & 79 deletions x/gamm/keeper/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ func calcSpotPriceWithSwapFee(
return spotPrice.Mul(scale)
}

func solveConstantFunctionInvariant(
tokenBalanceFixed,
tokenWeightFixed,
tokenBalanceUnknown,
tokenWeightUnknown,
tokenAmountFixed sdk.Dec,
) sdk.Dec {
weightRatio := tokenWeightFixed.Quo(tokenWeightUnknown)
y := tokenBalanceFixed.Quo(tokenBalanceFixed.Add(tokenAmountFixed))
foo := osmomath.Pow(y, weightRatio)

multiplier := sdk.OneDec().Sub(foo)
return tokenBalanceUnknown.Mul(multiplier)
}
mconcat marked this conversation as resolved.
Show resolved Hide resolved

// aO
func calcOutGivenIn(
tokenBalanceIn,
Expand All @@ -63,13 +78,10 @@ func calcOutGivenIn(
tokenAmountIn,
swapFee sdk.Dec,
) sdk.Dec {
weightRatio := tokenWeightIn.Quo(tokenWeightOut)
adjustedIn := sdk.OneDec().Sub(swapFee)
adjustedIn = tokenAmountIn.Mul(adjustedIn)
y := tokenBalanceIn.Quo(tokenBalanceIn.Add(adjustedIn))
foo := osmomath.Pow(y, weightRatio)
bar := sdk.OneDec().Sub(foo)
return tokenBalanceOut.Mul(bar)
// deduct swapfee on the in asset
tokenAmountIn = tokenAmountIn.Mul(sdk.OneDec().Sub(swapFee))
tokenAmountOut := solveConstantFunctionInvariant(tokenBalanceIn, tokenWeightIn, tokenBalanceOut, tokenWeightOut, tokenAmountIn)
return tokenAmountOut
}

// aI
Expand All @@ -81,120 +93,124 @@ func calcInGivenOut(
tokenAmountOut,
swapFee sdk.Dec,
) sdk.Dec {
weightRatio := tokenWeightOut.Quo(tokenWeightIn)
diff := tokenBalanceOut.Sub(tokenAmountOut)
y := tokenBalanceOut.Quo(diff)
foo := osmomath.Pow(y, weightRatio)
foo = foo.Sub(one)
tokenAmountIn := sdk.OneDec().Sub(swapFee)
return (tokenBalanceIn.Mul(foo)).Quo(tokenAmountIn)
// provide negative tokenOutAmount as it decreases pool liquidity
tokenAmountIn := solveConstantFunctionInvariant(tokenBalanceOut, tokenWeightOut, tokenBalanceIn, tokenWeightIn, tokenAmountOut.Neg()).Neg()
// deduct swapfee on the in asset
mconcat marked this conversation as resolved.
Show resolved Hide resolved
tokenAmountInBeforeFee := tokenAmountIn.Quo(sdk.OneDec().Sub(swapFee))
return tokenAmountInBeforeFee

}

// pAo
func calcPoolOutGivenSingleIn(
tokenBalanceIn,
tokenWeightIn,
poolSupply,
totalWeight,
tokenAmountIn,
func weightDelta(
mconcat marked this conversation as resolved.
Show resolved Hide resolved
normalizedWeight,
beforeWeight,
afterWeight sdk.Dec,
) (unknownNewBalance sdk.Dec) {
deltaRatio := afterWeight.Quo(beforeWeight)
// newBalTo = poolRatio^(1/weightTo) * balTo;
return osmomath.Pow(deltaRatio, normalizedWeight)
}

func feeRatio(
normalizedWeight,
swapFee sdk.Dec,
) sdk.Dec {
normalizedWeight := tokenWeightIn.Quo(totalWeight)
zaz := (sdk.OneDec().Sub(normalizedWeight)).Mul(swapFee)
tokenAmountInAfterFee := tokenAmountIn.Mul(sdk.OneDec().Sub(zaz))
zar := (sdk.OneDec().Sub(normalizedWeight)).Mul(swapFee)
return sdk.OneDec().Sub(zar)
}

func tokenDiffGivenPoolDiff(
mconcat marked this conversation as resolved.
Show resolved Hide resolved
normalizedWeight,
tokenBalance,
poolSupply,
poolAmount sdk.Dec,
) sdk.Dec {
newPoolSupply := poolSupply.Add(poolAmount)

poolSupplyDelta := weightDelta(
sdk.OneDec().Quo(normalizedWeight), poolSupply, newPoolSupply)

newTokenBalanceIn := tokenBalanceIn.Add(tokenAmountInAfterFee)
tokenInRatio := newTokenBalanceIn.Quo(tokenBalanceIn)
newTokenBalance := tokenBalance.Mul(poolSupplyDelta)

// Do reverse order of fees charged in joinswap_ExternAmountIn, this way
// ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```
//uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;
return newTokenBalance.Sub(tokenBalance)
}

func poolDiffGivenTokenDiff(
mconcat marked this conversation as resolved.
Show resolved Hide resolved
normalizedWeight,
tokenBalance,
poolSupply,
tokenAmount sdk.Dec,
) sdk.Dec {
newTokenBalance := tokenBalance.Add(tokenAmount)

tokenDelta := weightDelta(
normalizedWeight, tokenBalance, newTokenBalance)
newPoolSupply := poolSupply.Mul(tokenDelta)

// uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;
poolRatio := osmomath.Pow(tokenInRatio, normalizedWeight)
newPoolSupply := poolRatio.Mul(poolSupply)
return newPoolSupply.Sub(poolSupply)
}

//tAi
func calcSingleInGivenPoolOut(
tokenBalanceIn,
tokenWeightIn,
normalizedTokenWeightIn,
poolSupply,
totalWeight,
poolAmountOut,
swapFee sdk.Dec,
) sdk.Dec {
normalizedWeight := tokenWeightIn.Quo(totalWeight)
newPoolSupply := poolSupply.Add(poolAmountOut)
poolRatio := newPoolSupply.Quo(poolSupply)

//uint newBalTi = poolRatio^(1/weightTi) * balTi;
boo := sdk.OneDec().Quo(normalizedWeight)
tokenInRatio := osmomath.Pow(poolRatio, boo)
newTokenBalanceIn := tokenInRatio.Mul(tokenBalanceIn)
tokenAmountInAfterFee := newTokenBalanceIn.Sub(tokenBalanceIn)
// Do reverse order of fees charged in joinswap_ExternAmountIn, this way
// ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```
//uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;
zar := (sdk.OneDec().Sub(normalizedWeight)).Mul(swapFee)
return tokenAmountInAfterFee.Quo(sdk.OneDec().Sub(zar))
tokenAmountIn := tokenDiffGivenPoolDiff(normalizedTokenWeightIn, tokenBalanceIn, poolSupply, poolAmountOut)
tokenAmountInBeforeFee := tokenAmountIn.Quo(feeRatio(normalizedTokenWeightIn, swapFee))
return tokenAmountInBeforeFee
}

// pAo
func calcPoolOutGivenSingleIn(
tokenBalanceIn,
normalizedTokenWeightIn,
poolSupply,
tokenAmountIn,
swapFee sdk.Dec,
) sdk.Dec {
tokenAmountInAfterFee := tokenAmountIn.Mul(feeRatio(normalizedTokenWeightIn, swapFee))
poolAmountOut := poolDiffGivenTokenDiff(normalizedTokenWeightIn, tokenBalanceIn, poolSupply, tokenAmountInAfterFee)
return poolAmountOut
}

// tAo
func calcSingleOutGivenPoolIn(
tokenBalanceOut,
tokenWeightOut,
normalizedTokenWeightOut,
poolSupply,
totalWeight,
poolAmountIn,
swapFee sdk.Dec,
exitFee sdk.Dec,
) sdk.Dec {
normalizedWeight := tokenWeightOut.Quo(totalWeight)
// charge exit fee on the pool token side
// pAiAfterExitFee = pAi*(1-exitFee)
poolAmountInAfterExitFee := poolAmountIn.Mul(sdk.OneDec().Sub(exitFee))
newPoolSupply := poolSupply.Sub(poolAmountInAfterExitFee)
poolRatio := newPoolSupply.Quo(poolSupply)

// newBalTo = poolRatio^(1/weightTo) * balTo;

tokenOutRatio := osmomath.Pow(poolRatio, sdk.OneDec().Quo(normalizedWeight))
newTokenBalanceOut := tokenOutRatio.Mul(tokenBalanceOut)

tokenAmountOutBeforeSwapFee := tokenBalanceOut.Sub(newTokenBalanceOut)

// charge swap fee on the output token side
//uint tAo = tAoBeforeSwapFee * (1 - (1-weightTo) * swapFee)
zaz := (sdk.OneDec().Sub(normalizedWeight)).Mul(swapFee)
tokenAmountOut := tokenAmountOutBeforeSwapFee.Mul(sdk.OneDec().Sub(zaz))
return tokenAmountOut
tokenAmountOut := tokenDiffGivenPoolDiff(normalizedTokenWeightOut, tokenBalanceOut, poolSupply, poolAmountInAfterExitFee.Neg()).Neg()
tokenAmountOutAfterFee := tokenAmountOut.Mul(feeRatio(normalizedTokenWeightOut, swapFee))
return tokenAmountOutAfterFee
}

// pAi
func calcPoolInGivenSingleOut(
tokenBalanceOut,
tokenWeightOut,
normalizedTokenWeightOut,
poolSupply,
totalWeight,
tokenAmountOut,
swapFee sdk.Dec,
exitFee sdk.Dec,
) sdk.Dec {
// charge swap fee on the output token side
normalizedWeight := tokenWeightOut.Quo(totalWeight)
//uint tAoBeforeSwapFee = tAo / (1 - (1-weightTo) * swapFee) ;
zoo := sdk.OneDec().Sub(normalizedWeight)
zar := zoo.Mul(swapFee)
tokenAmountOutBeforeSwapFee := tokenAmountOut.Quo(sdk.OneDec().Sub(zar))

newTokenBalanceOut := tokenBalanceOut.Sub(tokenAmountOutBeforeSwapFee)
tokenOutRatio := newTokenBalanceOut.Quo(tokenBalanceOut)
tokenAmountOutBeforeFee := tokenAmountOut.Quo(feeRatio(normalizedTokenWeightOut, swapFee))

//uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;
poolRatio := osmomath.Pow(tokenOutRatio, normalizedWeight)
newPoolSupply := poolRatio.Mul(poolSupply)
poolAmountInAfterExitFee := poolSupply.Sub(newPoolSupply)
poolAmountIn := poolDiffGivenTokenDiff(normalizedTokenWeightOut, tokenBalanceOut, poolSupply, tokenAmountOutBeforeFee.Neg()).Neg()

// charge exit fee on the pool token side
// pAi = pAiAfterExitFee/(1-exitFee)
return poolAmountInAfterExitFee.Quo(sdk.OneDec().Sub(exitFee))
poolAmountInBeforeFee := poolAmountIn.Quo(sdk.OneDec().Sub(exitFee))
return poolAmountInBeforeFee
}
9 changes: 6 additions & 3 deletions x/gamm/keeper/math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ func TestCalcPoolOutGivenSingleIn(t *testing.T) {
swapFee, err := sdk.NewDecFromStr("0.15")
require.NoError(t, err)

s := calcPoolOutGivenSingleIn(tokenBalanceIn, tokenWeightIn, poolSupply, totalWeight, tokenAmountIn, swapFee)
normalizedWeight := tokenWeightIn.Quo(totalWeight)
s := calcPoolOutGivenSingleIn(tokenBalanceIn, normalizedWeight, poolSupply, tokenAmountIn, swapFee)

expectedDec, err := sdk.NewDecFromStr("18.6519592")
require.NoError(t, err)
Expand Down Expand Up @@ -185,7 +186,8 @@ func TestCalcSingleOutGivenPoolIn(t *testing.T) {
swapFee, err := sdk.NewDecFromStr("0.15")
require.NoError(t, err)

s := calcSingleOutGivenPoolIn(tokenBalanceOut, tokenWeightOut, poolSupply, totalWeight, poolAmountIn, swapFee, sdk.ZeroDec())
normalizedWeight := tokenWeightOut.Quo(totalWeight)
s := calcSingleOutGivenPoolIn(tokenBalanceOut, normalizedWeight, poolSupply, poolAmountIn, swapFee, sdk.ZeroDec())

expectedDec, err := sdk.NewDecFromStr("31.77534976")
require.NoError(t, err)
Expand All @@ -212,7 +214,8 @@ func TestCalcPoolInGivenSingleOut(t *testing.T) {
swapFee, err := sdk.NewDecFromStr("0.15")
require.NoError(t, err)

s := calcPoolInGivenSingleOut(tokenBalanceOut, tokenWeightOut, poolSupply, totalWeight, tokenAmountOut, swapFee, sdk.ZeroDec())
normalizedWeight := tokenWeightOut.Quo(totalWeight)
s := calcPoolInGivenSingleOut(tokenBalanceOut, normalizedWeight, poolSupply, tokenAmountOut, swapFee, sdk.ZeroDec())

expectedDec, err := sdk.NewDecFromStr("90.29092777")
require.NoError(t, err)
Expand Down
16 changes: 8 additions & 8 deletions x/gamm/keeper/pool_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ func (k Keeper) JoinSwapExternAmountIn(
return sdk.Int{}, err
}

normalizedWeight := PoolAsset.Weight.ToDec().Quo(pool.GetTotalWeight().ToDec())
shareOutAmount = calcPoolOutGivenSingleIn(
PoolAsset.Token.Amount.ToDec(),
PoolAsset.Weight.ToDec(),
normalizedWeight,
pool.GetTotalShares().Amount.ToDec(),
pool.GetTotalWeight().ToDec(),
tokenIn.Amount.ToDec(),
pool.GetPoolSwapFee(),
).TruncateInt()
Expand Down Expand Up @@ -259,11 +259,11 @@ func (k Keeper) JoinSwapShareAmountOut(
return sdk.Int{}, err
}

normalizedWeight := PoolAsset.Weight.ToDec().Quo(pool.GetTotalWeight().ToDec())
tokenInAmount = calcSingleInGivenPoolOut(
PoolAsset.Token.Amount.ToDec(),
PoolAsset.Weight.ToDec(),
normalizedWeight,
pool.GetTotalShares().Amount.ToDec(),
pool.GetTotalWeight().ToDec(),
shareOutAmount.ToDec(),
pool.GetPoolSwapFee(),
).TruncateInt()
Expand Down Expand Up @@ -411,11 +411,11 @@ func (k Keeper) ExitSwapShareAmountIn(
return sdk.Int{}, err
}

normalizedWeight := PoolAsset.Weight.ToDec().Quo(pool.GetTotalWeight().ToDec())
tokenOutAmount = calcSingleOutGivenPoolIn(
PoolAsset.Token.Amount.ToDec(),
PoolAsset.Weight.ToDec(),
normalizedWeight,
pool.GetTotalShares().Amount.ToDec(),
pool.GetTotalWeight().ToDec(),
shareInAmount.ToDec(),
pool.GetPoolSwapFee(),
pool.GetPoolExitFee(),
Expand Down Expand Up @@ -496,11 +496,11 @@ func (k Keeper) ExitSwapExternAmountOut(
return sdk.Int{}, err
}

normalizedWeight := PoolAsset.Weight.ToDec().Quo(pool.GetTotalWeight().ToDec())
shareInAmount = calcPoolInGivenSingleOut(
PoolAsset.Token.Amount.ToDec(),
PoolAsset.Weight.ToDec(),
normalizedWeight,
pool.GetTotalShares().Amount.ToDec(),
pool.GetTotalWeight().ToDec(),
tokenOut.Amount.ToDec(),
pool.GetPoolSwapFee(),
pool.GetPoolExitFee(),
Expand Down