diff --git a/x/amm/types/calc_exit_pool.go b/x/amm/types/calc_exit_pool.go index 0b88febae..4a7334afc 100644 --- a/x/amm/types/calc_exit_pool.go +++ b/x/amm/types/calc_exit_pool.go @@ -141,9 +141,15 @@ func CalcExitPool( targetWeightIn := sdkmath.LegacyOneDec().Sub(targetWeightOut) // weight breaking fee as in Plasma pool - weightOut := GetDenomOracleAssetWeight(ctx, pool.PoolId, oracleKeeper, newAssetPools, tokenOutDenom) - weightIn := sdkmath.LegacyOneDec().Sub(weightOut) - weightBreakingFee := GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut, distanceDiff, params) + finalWeightOut := GetDenomOracleAssetWeight(ctx, pool.PoolId, oracleKeeper, newAssetPools, tokenOutDenom) + finalWeightIn := sdkmath.LegacyOneDec().Sub(finalWeightOut) + initialAssetPools, err := pool.NewPoolAssetsAfterSwap(ctx, + sdk.NewCoins(), + sdk.NewCoins(), accountedAssets, + ) + initialWeightOut := GetDenomOracleAssetWeight(ctx, pool.PoolId, oracleKeeper, initialAssetPools, tokenOutDenom) + initialWeightIn := sdkmath.LegacyOneDec().Sub(initialWeightOut) + weightBreakingFee := GetWeightBreakingFee(finalWeightIn, finalWeightOut, targetWeightIn, targetWeightOut, initialWeightIn, initialWeightOut, distanceDiff, params) tokenOutAmount := oracleOutAmount.Mul(sdkmath.LegacyOneDec().Sub(weightBreakingFee)).RoundInt() return sdk.Coins{sdk.NewCoin(tokenOutDenom, tokenOutAmount)}, weightBreakingFee.Neg(), nil diff --git a/x/amm/types/pool_join_pool.go b/x/amm/types/pool_join_pool.go index 57bac1ee3..6d54f137e 100644 --- a/x/amm/types/pool_join_pool.go +++ b/x/amm/types/pool_join_pool.go @@ -194,9 +194,16 @@ func (p *Pool) JoinPool( targetWeightOut := sdkmath.LegacyOneDec().Sub(targetWeightIn) // weight breaking fee as in Plasma pool - weightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenInDenom) - weightOut := sdkmath.LegacyOneDec().Sub(weightIn) - weightBreakingFee := GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut, distanceDiff, params) + finalWeightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenInDenom) + finalWeightOut := sdkmath.LegacyOneDec().Sub(finalWeightIn) + + initialAssetPools, err := p.NewPoolAssetsAfterSwap(ctx, + sdk.NewCoins(), + sdk.NewCoins(), accountedAssets, + ) + initialWeightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, initialAssetPools, tokenInDenom) + initialWeightOut := sdkmath.LegacyOneDec().Sub(initialWeightIn) + weightBreakingFee := GetWeightBreakingFee(finalWeightIn, finalWeightOut, targetWeightIn, targetWeightOut, initialWeightIn, initialWeightOut, distanceDiff, params) // weight recovery reward = weight breaking fee * weight breaking fee portion weightRecoveryReward := weightBreakingFee.Mul(params.WeightBreakingFeePortion) diff --git a/x/amm/types/swap_in_amt_given_out.go b/x/amm/types/swap_in_amt_given_out.go index 0713d1fe1..efac43331 100644 --- a/x/amm/types/swap_in_amt_given_out.go +++ b/x/amm/types/swap_in_amt_given_out.go @@ -132,9 +132,15 @@ func (p *Pool) SwapInAmtGivenOut( targetWeightOut := GetDenomNormalizedWeight(newAssetPools, tokenOut.Denom) // weight breaking fee as in Plasma pool - weightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenInDenom) - weightOut := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenOut.Denom) - weightBreakingFee := GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut, distanceDiff, params) + finalWeightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenInDenom) + finalWeightOut := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenOut.Denom) + initialAssetPools, err := p.NewPoolAssetsAfterSwap(ctx, + sdk.NewCoins(), + sdk.NewCoins(), accountedAssets, + ) + initialWeightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, initialAssetPools, tokenInDenom) + initialWeightOut := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, initialAssetPools, tokenOut.Denom) + weightBreakingFee := GetWeightBreakingFee(finalWeightIn, finalWeightOut, targetWeightIn, targetWeightOut, initialWeightIn, initialWeightOut, distanceDiff, params) // weightBreakingFeePerpetualFactor is 1 if not send by perpetual weightBreakingFee = weightBreakingFee.Mul(weightBreakingFeePerpetualFactor) diff --git a/x/amm/types/swap_out_amt_given_in.go b/x/amm/types/swap_out_amt_given_in.go index b49c9ba41..e703d9be3 100644 --- a/x/amm/types/swap_out_amt_given_in.go +++ b/x/amm/types/swap_out_amt_given_in.go @@ -302,9 +302,15 @@ func (p *Pool) SwapOutAmtGivenIn( targetWeightOut := GetDenomNormalizedWeight(newAssetPools, tokenOutDenom) // weight breaking fee as in Plasma pool - weightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenIn.Denom) - weightOut := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenOutDenom) - weightBreakingFee := GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut, distanceDiff, params) + finalWeightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenIn.Denom) + finalWeightOut := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, newAssetPools, tokenOutDenom) + initialAssetPools, err := p.NewPoolAssetsAfterSwap(ctx, + sdk.NewCoins(), + sdk.NewCoins(), accountedAssets, + ) + initialWeightIn := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, initialAssetPools, tokenIn.Denom) + initialWeightOut := GetDenomOracleAssetWeight(ctx, p.PoolId, oracleKeeper, initialAssetPools, tokenOutDenom) + weightBreakingFee := GetWeightBreakingFee(finalWeightIn, finalWeightOut, targetWeightIn, targetWeightOut, initialWeightIn, initialWeightOut, distanceDiff, params) // weightBreakingFeePerpetualFactor is 1 if not send by perpetual weightBreakingFee = weightBreakingFee.Mul(weightBreakingFeePerpetualFactor) diff --git a/x/amm/types/utils.go b/x/amm/types/utils.go index 5128c7db8..539daff91 100644 --- a/x/amm/types/utils.go +++ b/x/amm/types/utils.go @@ -60,16 +60,23 @@ func ApplyDiscount(swapFee sdkmath.LegacyDec, discount sdkmath.LegacyDec) sdkmat return swapFee } -func GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut sdkmath.LegacyDec, distanceDiff sdkmath.LegacyDec, params Params) sdkmath.LegacyDec { +// GetWeightBreakingFee When distanceDiff > 0, pool is getting worse so we calculate WBF based on final weight +// When distanceDiff < 0, pool is improving, we need to use initial weights. Say target is 50:50, initially pool is 80:20 and now after it is becoming 30:70, +// this is improving the pool but with finalWeightOut/finalWeightIn it will be 30/70 which doesn't provide enough bonus to user +func GetWeightBreakingFee(finalWeightIn, finalWeightOut, targetWeightIn, targetWeightOut, initialWeightIn, initialWeightOut sdkmath.LegacyDec, distanceDiff sdkmath.LegacyDec, params Params) sdkmath.LegacyDec { weightBreakingFee := sdkmath.LegacyZeroDec() - if !weightOut.IsZero() && !weightIn.IsZero() && !targetWeightOut.IsZero() && !targetWeightIn.IsZero() && !params.WeightBreakingFeeMultiplier.IsZero() { + if !params.WeightBreakingFeeMultiplier.IsZero() { // (45/55*60/40) ^ 2.5 if distanceDiff.IsPositive() { - weightBreakingFee = params.WeightBreakingFeeMultiplier. - Mul(Pow(weightIn.Mul(targetWeightOut).Quo(weightOut).Quo(targetWeightIn), params.WeightBreakingFeeExponent)) + if !finalWeightOut.IsZero() && !finalWeightIn.IsZero() && !targetWeightOut.IsZero() && !targetWeightIn.IsZero() { + weightBreakingFee = params.WeightBreakingFeeMultiplier. + Mul(Pow(finalWeightIn.Mul(targetWeightOut).Quo(finalWeightOut).Quo(targetWeightIn), params.WeightBreakingFeeExponent)) + } } else { - weightBreakingFee = params.WeightBreakingFeeMultiplier. - Mul(Pow(weightOut.Mul(targetWeightIn).Quo(weightIn).Quo(targetWeightOut), params.WeightBreakingFeeExponent)) + if !initialWeightOut.IsZero() && !initialWeightIn.IsZero() && !targetWeightOut.IsZero() && !targetWeightIn.IsZero() { + weightBreakingFee = params.WeightBreakingFeeMultiplier. + Mul(Pow(initialWeightOut.Mul(targetWeightIn).Quo(initialWeightIn).Quo(targetWeightOut), params.WeightBreakingFeeExponent)) + } } if weightBreakingFee.GT(sdkmath.LegacyNewDecWithPrec(99, 2)) {