Skip to content

Commit

Permalink
treat pool with zero pool coin supply as depleted
Browse files Browse the repository at this point in the history
also change Mul/QuoTruncate to Mul/Quo.

fixes tendermint#364
  • Loading branch information
hallazzang committed May 27, 2021
1 parent c55b4ad commit 25dbb2d
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 70 deletions.
82 changes: 43 additions & 39 deletions x/liquidity/keeper/liquidity_pool.go
Expand Up @@ -77,32 +77,32 @@ func (k Keeper) CreatePool(ctx sdk.Context, msg *types.MsgCreatePool) (types.Poo
poolName := types.PoolName(reserveCoinDenoms, msg.PoolTypeId)
reserveAcc := types.GetPoolReserveAcc(poolName)

poolCreator := msg.GetPoolCreator()
accPoolCreator := k.accountKeeper.GetAccount(ctx, poolCreator)
poolCreatorBalances := k.bankKeeper.GetAllBalances(ctx, accPoolCreator.GetAddress())

if !poolCreatorBalances.IsAllGTE(msg.DepositCoins) {
return types.Pool{}, types.ErrInsufficientBalance
poolCoinDenom := types.GetPoolCoinDenom(poolName)
pool := types.Pool{
//Id: will set on SetPoolAtomic
TypeId: msg.PoolTypeId,
ReserveCoinDenoms: reserveCoinDenoms,
ReserveAccountAddress: reserveAcc.String(),
PoolCoinDenom: poolCoinDenom,
}

reserveCoins := k.GetReserveCoins(ctx, pool)

poolCreator := msg.GetPoolCreator()
poolCreatorBalances := k.bankKeeper.GetAllBalances(ctx, poolCreator)

for _, coin := range msg.DepositCoins {
if coin.Amount.LT(params.MinInitDepositAmount) {
if coin.Amount.Add(reserveCoins.AmountOf(coin.Denom)).LT(params.MinInitDepositAmount) {
return types.Pool{}, types.ErrLessThanMinInitDeposit
}
}

if !poolCreatorBalances.IsAllGTE(params.PoolCreationFee.Add(msg.DepositCoins...)) {
return types.Pool{}, types.ErrInsufficientPoolCreationFee
if !poolCreatorBalances.IsAllGTE(msg.DepositCoins) {
return types.Pool{}, types.ErrInsufficientBalance
}

PoolCoinDenom := types.GetPoolCoinDenom(poolName)

pool := types.Pool{
//Id: will set on SetPoolAtomic
TypeId: msg.PoolTypeId,
ReserveCoinDenoms: reserveCoinDenoms,
ReserveAccountAddress: reserveAcc.String(),
PoolCoinDenom: PoolCoinDenom,
if !poolCreatorBalances.IsAllGTE(msg.DepositCoins.Add(params.PoolCreationFee...)) {
return types.Pool{}, types.ErrInsufficientPoolCreationFee
}

batchEscrowAcc := k.accountKeeper.GetModuleAddress(types.ModuleName)
Expand Down Expand Up @@ -136,8 +136,8 @@ func (k Keeper) CreatePool(ctx sdk.Context, msg *types.MsgCreatePool) (types.Poo

k.SetPoolBatch(ctx, batch)

reserveCoins := k.GetReserveCoins(ctx, pool)
lastReserveRatio := sdk.NewDecFromInt(reserveCoins[0].Amount).QuoTruncate(sdk.NewDecFromInt(reserveCoins[1].Amount))
reserveCoins = k.GetReserveCoins(ctx, pool)
lastReserveRatio := sdk.NewDecFromInt(reserveCoins[0].Amount).Quo(sdk.NewDecFromInt(reserveCoins[1].Amount))
logger := k.Logger(ctx)
logger.Debug("createPool", msg, "pool", pool, "reserveCoins", reserveCoins, "lastReserveRatio", lastReserveRatio)
return pool, nil
Expand Down Expand Up @@ -172,10 +172,10 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,

reserveCoins := k.GetReserveCoins(ctx, pool)

// reinitialize pool in case of reserve coins has run out
if reserveCoins.IsZero() {
// reinitialize pool if the pool is depleted
if k.IsDepletedPool(ctx, pool) {
for _, depositCoin := range msg.Msg.DepositCoins {
if depositCoin.Amount.LT(params.MinInitDepositAmount) {
if depositCoin.Amount.Add(reserveCoins.AmountOf(depositCoin.Denom)).LT(params.MinInitDepositAmount) {
return types.ErrLessThanMinInitDeposit
}
}
Expand All @@ -202,10 +202,10 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,
msg.ToBeDeleted = true
k.SetPoolBatchDepositMsgState(ctx, msg.Msg.PoolId, msg)

reserveCoins := k.GetReserveCoins(ctx, pool)
reserveCoins = k.GetReserveCoins(ctx, pool)
lastReserveCoinA := sdk.NewDecFromInt(reserveCoins[0].Amount)
lastReserveCoinB := sdk.NewDecFromInt(reserveCoins[1].Amount)
lastReserveRatio := lastReserveCoinA.QuoTruncate(lastReserveCoinB)
lastReserveRatio := lastReserveCoinA.Quo(lastReserveCoinB)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeDepositToPool,
Expand Down Expand Up @@ -236,13 +236,13 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,
// Decimal Error, divide the Int coin amount by the Decimal Rate and erase the decimal point to deposit a lower value
lastReserveCoinA := sdk.NewDecFromInt(reserveCoins[0].Amount)
lastReserveCoinB := sdk.NewDecFromInt(reserveCoins[1].Amount)
lastReserveRatio := lastReserveCoinA.QuoTruncate(lastReserveCoinB)
lastReserveRatio := lastReserveCoinA.Quo(lastReserveCoinB)

depositCoinA := depositCoins[0]
depositCoinB := depositCoins[1]
depositCoinAmountA := depositCoinA.Amount
depositCoinAmountB := depositCoinB.Amount
depositableCoinAmountA := depositCoinB.Amount.ToDec().MulTruncate(lastReserveRatio).TruncateInt()
depositableCoinAmountA := depositCoinB.Amount.ToDec().Mul(lastReserveRatio).TruncateInt()

acceptedCoins := sdk.NewCoins()
refundedCoins := sdk.NewCoins()
Expand All @@ -251,7 +251,7 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,

// handle when depositing coin A amount is less than, greater than or equal to depositable amount
if depositCoinA.Amount.LT(depositableCoinAmountA) {
depositCoinAmountB = depositCoinA.Amount.ToDec().QuoTruncate(lastReserveRatio).TruncateInt()
depositCoinAmountB = depositCoinA.Amount.ToDec().Quo(lastReserveRatio).TruncateInt()
acceptedCoins = sdk.NewCoins(depositCoinA, sdk.NewCoin(depositCoinB.Denom, depositCoinAmountB))

inputs = append(inputs, banktypes.NewInput(batchEscrowAcc, acceptedCoins))
Expand All @@ -265,7 +265,7 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,
outputs = append(outputs, banktypes.NewOutput(depositor, refundedCoins))
}
} else if depositCoinA.Amount.GT(depositableCoinAmountA) {
depositCoinAmountA = depositCoinB.Amount.ToDec().MulTruncate(lastReserveRatio).TruncateInt()
depositCoinAmountA = depositCoinB.Amount.ToDec().Mul(lastReserveRatio).TruncateInt()
acceptedCoins = sdk.NewCoins(depositCoinB, sdk.NewCoin(depositCoinA.Denom, depositCoinAmountA))

inputs = append(inputs, banktypes.NewInput(batchEscrowAcc, acceptedCoins))
Expand Down Expand Up @@ -313,7 +313,7 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,
afterReserveCoins := k.GetReserveCoins(ctx, pool)
afterReserveCoinA := sdk.NewDecFromInt(afterReserveCoins[0].Amount)
afterReserveCoinB := sdk.NewDecFromInt(afterReserveCoins[1].Amount)
afterReserveRatio := afterReserveCoinA.QuoTruncate(afterReserveCoinB)
afterReserveRatio := afterReserveCoinA.Quo(afterReserveCoinB)
poolCoinTotalSupplyDec := sdk.NewDecFromInt(poolCoinTotalSupply)
mintPoolCoinDec := sdk.NewDecFromInt(mintPoolCoin.Amount)
depositCoinADec := sdk.NewDecFromInt(depositCoinA.Amount)
Expand Down Expand Up @@ -345,7 +345,7 @@ func (k Keeper) DepositLiquidityPool(ctx sdk.Context, msg types.DepositMsgState,
)

reserveCoins = k.GetReserveCoins(ctx, pool)
lastReserveRatio = sdk.NewDecFromInt(reserveCoins[0].Amount).QuoTruncate(sdk.NewDecFromInt(reserveCoins[1].Amount))
lastReserveRatio = sdk.NewDecFromInt(reserveCoins[0].Amount).Quo(sdk.NewDecFromInt(reserveCoins[1].Amount))

logger := k.Logger(ctx)
logger.Debug("deposit", msg, "pool", pool, "inputs", inputs, "outputs", outputs, "reserveCoins", reserveCoins, "lastReserveRatio", lastReserveRatio)
Expand Down Expand Up @@ -393,7 +393,7 @@ func (k Keeper) WithdrawLiquidityPool(ctx sdk.Context, msg types.WithdrawMsgStat
// Calculate withdraw amount of respective reserve coin considering fees and pool coin's totally supply
for _, reserveCoin := range reserveCoins {
// WithdrawAmount = ReserveAmount * PoolCoinAmount * WithdrawFeeProportion / TotalSupply
withdrawAmt := reserveCoin.Amount.Mul(msg.Msg.PoolCoin.Amount).ToDec().MulTruncate(withdrawProportion).TruncateInt().Quo(poolCoinTotalSupply)
withdrawAmt := reserveCoin.Amount.Mul(msg.Msg.PoolCoin.Amount).ToDec().Mul(withdrawProportion).TruncateInt().Quo(poolCoinTotalSupply)
withdrawCoins = append(withdrawCoins, sdk.NewCoin(reserveCoin.Denom, withdrawAmt))
}
}
Expand Down Expand Up @@ -465,7 +465,7 @@ func (k Keeper) WithdrawLiquidityPool(ctx sdk.Context, msg types.WithdrawMsgStat
if reserveCoins.IsZero() {
lastReserveRatio = sdk.ZeroDec()
} else {
lastReserveRatio = sdk.NewDecFromInt(reserveCoins[0].Amount).QuoTruncate(sdk.NewDecFromInt(reserveCoins[1].Amount))
lastReserveRatio = sdk.NewDecFromInt(reserveCoins[0].Amount).Quo(sdk.NewDecFromInt(reserveCoins[1].Amount))
}

logger := k.Logger(ctx)
Expand All @@ -481,6 +481,11 @@ func (k Keeper) GetPoolCoinTotalSupply(ctx sdk.Context, pool types.Pool) sdk.Int
return total.AmountOf(pool.PoolCoinDenom)
}

// IsDepletedPool returns true if the pool is depleted.
func (k Keeper) IsDepletedPool(ctx sdk.Context, pool types.Pool) bool {
return !k.GetPoolCoinTotalSupply(ctx, pool).IsPositive()
}

// GetPoolCoinTotal returns total supply of pool coin of the pool in form of sdk.Coin
func (k Keeper) GetPoolCoinTotal(ctx sdk.Context, pool types.Pool) sdk.Coin {
return sdk.NewCoin(pool.PoolCoinDenom, k.GetPoolCoinTotalSupply(ctx, pool))
Expand Down Expand Up @@ -738,8 +743,7 @@ func (k Keeper) ValidateMsgWithdrawLiquidityPool(ctx sdk.Context, msg types.MsgW
}

poolCoinTotalSupply := k.GetPoolCoinTotalSupply(ctx, pool)

if !poolCoinTotalSupply.IsPositive() || !k.GetReserveCoins(ctx, pool).IsAllPositive() {
if !poolCoinTotalSupply.IsPositive() {
return types.ErrDepletedPool
}

Expand All @@ -765,17 +769,17 @@ func (k Keeper) ValidateMsgSwapWithinBatch(ctx sdk.Context, msg types.MsgSwapWit
return types.ErrNotMatchedReserveCoin
}

if k.IsDepletedPool(ctx, pool) {
return types.ErrDepletedPool
}

params := k.GetParams(ctx)

// can not exceed max order ratio of reserve coins that can be ordered at a order
reserveCoinAmt := k.GetReserveCoins(ctx, pool).AmountOf(msg.OfferCoin.Denom)

if !reserveCoinAmt.IsPositive() {
return types.ErrDepletedPool
}

// Decimal Error, Multiply the Int coin amount by the Decimal Rate and erase the decimal point to order a lower value
maximumOrderableAmt := reserveCoinAmt.ToDec().MulTruncate(params.MaxOrderAmountRatio).TruncateInt()
maximumOrderableAmt := reserveCoinAmt.ToDec().Mul(params.MaxOrderAmountRatio).TruncateInt()
if msg.OfferCoin.Amount.GT(maximumOrderableAmt) {
return types.ErrExceededMaxOrderable
}
Expand Down

0 comments on commit 25dbb2d

Please sign in to comment.