Skip to content

Commit

Permalink
fix: consume all ReservedOfferCoinFee when full matched
Browse files Browse the repository at this point in the history
  • Loading branch information
dongsam committed Aug 24, 2021
1 parent 7fc0a08 commit da7d52e
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 22 deletions.
6 changes: 2 additions & 4 deletions client/docs/statik/statik.go

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions x/liquidity/keeper/invariants.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func ImmutablePoolPriceAfterWithdrawInvariant(reserveCoinA, reserveCoinB, withdr
}

// SwapMatchingInvariants checks swap matching results of both X to Y and Y to X cases.
func SwapMatchingInvariants(xToY, yToX []*types.SwapMsgState, matchResultXtoY, matchResultYtoX []types.MatchResult) {
func SwapMatchingInvariants(xToY, yToX []*types.SwapMsgState, matchResultXtoY, matchResultYtoX []*types.MatchResult) {
beforeMatchingXtoYLen := len(xToY)
beforeMatchingYtoXLen := len(yToX)
afterMatchingXtoYLen := len(matchResultXtoY)
Expand All @@ -237,7 +237,7 @@ func SwapMatchingInvariants(xToY, yToX []*types.SwapMsgState, matchResultXtoY, m
}

// SwapPriceInvariants checks swap price invariants.
func SwapPriceInvariants(matchResultXtoY, matchResultYtoX []types.MatchResult, poolXDelta, poolYDelta, poolXDelta2, poolYDelta2 sdk.Dec, result types.BatchResult) {
func SwapPriceInvariants(matchResultXtoY, matchResultYtoX []*types.MatchResult, poolXDelta, poolYDelta, poolXDelta2, poolYDelta2 sdk.Dec, result types.BatchResult) {
invariantCheckX := sdk.ZeroDec()
invariantCheckY := sdk.ZeroDec()

Expand Down Expand Up @@ -283,7 +283,7 @@ func SwapPriceDirectionInvariants(currentPoolPrice sdk.Dec, batchResult types.Ba
}

// SwapMsgStatesInvariants checks swap match result states invariants.
func SwapMsgStatesInvariants(matchResultXtoY, matchResultYtoX []types.MatchResult, matchResultMap map[uint64]types.MatchResult,
func SwapMsgStatesInvariants(matchResultXtoY, matchResultYtoX []*types.MatchResult, matchResultMap map[uint64]types.MatchResult,
swapMsgStates []*types.SwapMsgState, xToY, yToX []*types.SwapMsgState) {
if len(matchResultXtoY)+len(matchResultYtoX) != len(matchResultMap) {
panic("invalid length of match result")
Expand Down
28 changes: 19 additions & 9 deletions x/liquidity/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/tendermint/liquidity/app"
"github.com/tendermint/liquidity/x/liquidity"
"github.com/tendermint/liquidity/x/liquidity/types"
)

Expand Down Expand Up @@ -298,6 +299,20 @@ func TestMsgSwapWithinBatch(t *testing.T) {
},
types.MustParseCoinsNormalized("1000000000denomX,1000000000denomY"),
},
{
"",
types.DefaultSwapFeeRate,
&types.MsgSwapWithinBatch{
SwapRequesterAddress: user.String(),
PoolId: pool.Id,
SwapTypeId: pool.TypeId,
OfferCoin: sdk.NewCoin(DenomX, sdk.NewInt(10001)),
OfferCoinFee: sdk.NewCoin(DenomX, sdk.NewInt(16)),
DemandCoinDenom: DenomY,
OrderPrice: sdk.MustNewDecFromStr("1.00002"),
},
types.MustParseCoinsNormalized("999989983denomX,1000009984denomY"),
},
{
"",
types.DefaultSwapFeeRate,
Expand Down Expand Up @@ -400,23 +415,18 @@ func TestMsgSwapWithinBatch(t *testing.T) {

for _, tc := range cases {
cacheCtx, _ := ctx.CacheContext()
cacheCtx = cacheCtx.WithBlockHeight(1)
params.SwapFeeRate = tc.swapFeeRate
simapp.LiquidityKeeper.SetParams(cacheCtx, params)
_, err = simapp.LiquidityKeeper.SwapWithinBatch(cacheCtx, tc.msg, types.CancelOrderLifeSpan)

if tc.expectedErr == "" {
require.NoError(t, err)
poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(cacheCtx, tc.msg.PoolId)
require.True(t, found)
msgs := simapp.LiquidityKeeper.GetAllPoolBatchSwapMsgStates(cacheCtx, poolBatch)
require.Equal(t, 1, len(msgs))

executedCnt, err := simapp.LiquidityKeeper.SwapExecution(cacheCtx, poolBatch)
require.NoError(t, err)
require.Equal(t, uint64(1), executedCnt)
liquidity.EndBlocker(cacheCtx, simapp.LiquidityKeeper)
} else {
require.EqualError(t, err, tc.expectedErr)
}
moduleAccAddress := simapp.AccountKeeper.GetModuleAddress(types.ModuleName)
require.True(t, simapp.BankKeeper.GetAllBalances(cacheCtx, moduleAccAddress).IsZero())
require.Equal(t, tc.afterBalance, simapp.BankKeeper.GetAllBalances(cacheCtx, user))
}
}
4 changes: 2 additions & 2 deletions x/liquidity/keeper/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (k Keeper) SwapExecution(ctx sdk.Context, poolBatch types.PoolBatch) (uint6
}

// find order match, calculate pool delta with the total x, y amounts for the invariant check
var matchResultXtoY, matchResultYtoX []types.MatchResult
var matchResultXtoY, matchResultYtoX []*types.MatchResult

poolXDelta := sdk.ZeroDec()
poolYDelta := sdk.ZeroDec()
Expand Down Expand Up @@ -125,7 +125,7 @@ func (k Keeper) SwapExecution(ctx sdk.Context, poolBatch types.PoolBatch) (uint6
if _, ok := matchResultMap[match.SwapMsgState.MsgIndex]; ok {
return executedMsgCount, fmt.Errorf("duplicate match order")
}
matchResultMap[match.SwapMsgState.MsgIndex] = match
matchResultMap[match.SwapMsgState.MsgIndex] = *match
}

if BatchLogicInvariantCheckFlag {
Expand Down
12 changes: 8 additions & 4 deletions x/liquidity/types/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ func ValidateStateAndExpireOrders(swapMsgStates []*SwapMsgState, currentHeight i
}

// Check swap price validity using list of match result.
func CheckSwapPrice(matchResultXtoY, matchResultYtoX []MatchResult, swapPrice sdk.Dec) bool {
func CheckSwapPrice(matchResultXtoY, matchResultYtoX []*MatchResult, swapPrice sdk.Dec) bool {
if len(matchResultXtoY) == 0 && len(matchResultYtoX) == 0 {
return true
}
Expand All @@ -452,7 +452,7 @@ func CheckSwapPrice(matchResultXtoY, matchResultYtoX []MatchResult, swapPrice sd

// Find matched orders and set status for msgs
func FindOrderMatch(direction OrderDirection, swapMsgStates []*SwapMsgState, executableAmt, swapPrice sdk.Dec, height int64) (
matchResults []MatchResult, poolXDelta, poolYDelta sdk.Dec) {
matchResults []*MatchResult, poolXDelta, poolYDelta sdk.Dec) {
poolXDelta = sdk.ZeroDec()
poolYDelta = sdk.ZeroDec()

Expand Down Expand Up @@ -523,7 +523,7 @@ func FindOrderMatch(direction OrderDirection, swapMsgStates []*SwapMsgState, exe
if matchResult.OfferCoinFeeAmt.GT(matchResult.OfferCoinAmt) && matchResult.OfferCoinFeeAmt.GT(sdk.OneDec()) {
panic("bad OfferCoinFeeAmt")
}
matchResults = append(matchResults, matchResult)
matchResults = append(matchResults, &matchResult)
if direction == DirectionXtoY {
poolXDelta = poolXDelta.Add(matchResult.TransactedCoinAmt)
poolYDelta = poolYDelta.Sub(matchResult.ExchangedDemandCoinAmt)
Expand All @@ -543,7 +543,7 @@ func FindOrderMatch(direction OrderDirection, swapMsgStates []*SwapMsgState, exe
}

// UpdateSwapMsgStates updates SwapMsgStates using the MatchResults.
func UpdateSwapMsgStates(x, y sdk.Dec, xToY, yToX []*SwapMsgState, matchResultXtoY, matchResultYtoX []MatchResult) (
func UpdateSwapMsgStates(x, y sdk.Dec, xToY, yToX []*SwapMsgState, matchResultXtoY, matchResultYtoX []*MatchResult) (
[]*SwapMsgState, []*SwapMsgState, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec) {
sort.SliceStable(xToY, func(i, j int) bool {
return xToY[i].Msg.OrderPrice.GT(xToY[j].Msg.OrderPrice)
Expand Down Expand Up @@ -599,6 +599,10 @@ func UpdateSwapMsgStates(x, y sdk.Dec, xToY, yToX []*SwapMsgState, matchResultXt
sms.Succeeded = true
sms.ToBeDeleted = false
}
if sms.RemainingOfferCoin.Amount.IsZero() && sms.ReservedOfferCoinFee.Amount.IsPositive() {
match.OfferCoinFeeAmt = match.OfferCoinFeeAmt.Add(sms.ReservedOfferCoinFee.Amount.ToDec())
sms.ReservedOfferCoinFee.Amount = sdk.ZeroInt()
}
}

// Offset accumulated decimal error values
Expand Down

0 comments on commit da7d52e

Please sign in to comment.