Skip to content

Commit

Permalink
feat: fix division by zero issue (#808)
Browse files Browse the repository at this point in the history
* feat: fix division by zero issue

* feat: add error

* add test
  • Loading branch information
cryptokage1996 authored Sep 24, 2024
1 parent ca364fc commit 34798ce
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
3 changes: 3 additions & 0 deletions x/amm/types/calc_in_amt_given_out.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ func (p Pool) CalcInAmtGivenOut(
}

amountInWithoutSlippage := sdk.NewDecFromInt(tokenOut.Amount).Quo(rate)
if tokenAmountIn.IsZero(){
return sdk.Coin{}, sdk.ZeroDec(), ErrAmountTooLow
}
slippage = sdk.OneDec().Sub(amountInWithoutSlippage.Quo(tokenAmountIn))

// Ensure (1 - swapfee) is not zero to avoid division by zero
Expand Down
5 changes: 4 additions & 1 deletion x/amm/types/calc_out_amt_given_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ func (p Pool) CalcOutAmtGivenIn(
if err != nil {
return sdk.Coin{}, sdk.ZeroDec(), err
}
if tokenAmountOut.IsZero(){
return sdk.Coin{}, sdk.ZeroDec(), ErrAmountTooLow
}

rate, err := p.GetTokenARate(ctx, oracle, snapshot, tokenIn.Denom, tokenOutDenom, accountedPool)
if err != nil {
Expand All @@ -77,7 +80,7 @@ func (p Pool) CalcOutAmtGivenIn(
if amountOutWithoutSlippage.IsZero() {
return sdk.Coin{}, sdk.ZeroDec(), errorsmod.Wrapf(ErrInvalidMathApprox, "amount out without slippage must be positive")
}

slippage := sdk.OneDec().Sub(tokenAmountOut.Quo(amountOutWithoutSlippage))

// We ignore the decimal component, as we round down the token amount out.
Expand Down
24 changes: 24 additions & 0 deletions x/amm/types/swap_in_amt_given_out_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,29 @@ func (suite *TestSuite) TestSwapInAmtGivenOut() {
expTokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 36075037),
expErr: false,
},

{
desc: "tokenOut is zero",
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin(ptypes.BaseCurrency, 500_000_000),
Weight: sdk.NewInt(50),
},
{
Token: sdk.NewInt64Coin("uusdt", 1500_000_000),
Weight: sdk.NewInt(50),
},
},
useOracle: false,
externalLiquidityRatio: sdk.NewDec(10),
thresholdWeightDiff: sdk.NewDecWithPrec(20, 2),
tokenOut: sdk.NewInt64Coin("uusdt", 0),
inTokenDenom: ptypes.BaseCurrency,
swapFee: sdk.NewDecWithPrec(1, 2),
expRecoveryBonus: sdk.ZeroDec(),
expTokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 0),
expErr: true,
},
} {
suite.Run(tc.desc, func() {
suite.SetupTest()
Expand Down Expand Up @@ -193,6 +216,7 @@ func (suite *TestSuite) TestSwapInAmtGivenOut() {
tokenOut, _, _, weightBonus, err := pool.SwapInAmtGivenOut(suite.ctx, suite.app.OracleKeeper, &pool, sdk.Coins{tc.tokenOut}, tc.inTokenDenom, tc.swapFee, suite.app.AccountedPoolKeeper)
if tc.expErr {
suite.Require().Error(err)
suite.Require().EqualError(err, "amount too low")
} else {
suite.Require().NoError(err)
suite.Require().Equal(tokenOut.String(), tc.expTokenIn.String())
Expand Down
24 changes: 24 additions & 0 deletions x/amm/types/swap_out_amt_given_in_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,29 @@ func (suite *TestSuite) TestSwapOutAmtGivenIn() {
expTokenOut: sdk.NewInt64Coin("uusdt", 247913188),
expErr: false,
},

{
desc: "tokenOut is zero",
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin(ptypes.BaseCurrency, 500_000_000),
Weight: sdk.NewInt(50),
},
{
Token: sdk.NewInt64Coin("uusdt", 1500_000_000),
Weight: sdk.NewInt(50),
},
},
useOracle: false,
externalLiquidityRatio: sdk.NewDec(10),
thresholdWeightDiff: sdk.NewDecWithPrec(20, 2),
tokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 0),
outTokenDenom: "uusdt",
swapFee: sdk.NewDecWithPrec(1, 2),
expRecoveryBonus: sdk.ZeroDec(),
expTokenOut: sdk.NewInt64Coin("uusdt", 0),
expErr: true,
},
} {
suite.Run(tc.desc, func() {
suite.SetupTest()
Expand Down Expand Up @@ -603,6 +626,7 @@ func (suite *TestSuite) TestSwapOutAmtGivenIn() {
tokenOut, _, _, weightBonus, err := pool.SwapOutAmtGivenIn(suite.ctx, suite.app.OracleKeeper, &pool, sdk.Coins{tc.tokenIn}, tc.outTokenDenom, tc.swapFee, suite.app.AccountedPoolKeeper)
if tc.expErr {
suite.Require().Error(err)
suite.Require().EqualError(err, "amount too low")
} else {
suite.Require().NoError(err)
suite.Require().Equal(tokenOut.String(), tc.expTokenOut.String())
Expand Down

0 comments on commit 34798ce

Please sign in to comment.