code.vegaprotocol.io/vega@v0.79.0/core/liquidity/v2/amendments_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package liquidity_test
    17  
    18  import (
    19  	"context"
    20  	"testing"
    21  	"time"
    22  
    23  	"code.vegaprotocol.io/vega/core/idgeneration"
    24  	"code.vegaprotocol.io/vega/core/liquidity/v2"
    25  	"code.vegaprotocol.io/vega/core/types"
    26  	"code.vegaprotocol.io/vega/libs/crypto"
    27  	"code.vegaprotocol.io/vega/libs/num"
    28  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    29  
    30  	"github.com/golang/mock/gomock"
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  const (
    36  	market = "ETH/USD"
    37  )
    38  
    39  func TestAmendments(t *testing.T) {
    40  	var (
    41  		party = "party-1"
    42  		ctx   = context.Background()
    43  		tng   = newTestEngine(t)
    44  	)
    45  	defer tng.ctrl.Finish()
    46  
    47  	assert.EqualError(t,
    48  		tng.engine.CanAmend(nil, party, true),
    49  		liquidity.ErrPartyHaveNoLiquidityProvision.Error(),
    50  	)
    51  
    52  	lps, _ := types.LiquidityProvisionSubmissionFromProto(&commandspb.LiquidityProvisionSubmission{
    53  		MarketId:         market,
    54  		CommitmentAmount: "10000",
    55  		Fee:              "0.5",
    56  		Reference:        "ref-lp-submission-1",
    57  	})
    58  
    59  	now := time.Now()
    60  	zero := num.UintZero()
    61  	zeroD := num.DecimalZero()
    62  
    63  	idgen := idgeneration.New(crypto.RandomHash())
    64  	// initially submit our provision to be amended, does not matter what's in
    65  	tng.broker.EXPECT().Send(gomock.Any()).AnyTimes()
    66  	tng.auctionState.EXPECT().InAuction().Return(false).AnyTimes()
    67  	tng.auctionState.EXPECT().IsOpeningAuction().Return(false).AnyTimes()
    68  
    69  	_, err := tng.engine.SubmitLiquidityProvision(ctx, lps, party, idgen)
    70  	assert.NoError(t, err)
    71  	tng.engine.ResetSLAEpoch(now, zero, zero, zeroD)
    72  	tng.engine.ApplyPendingProvisions(ctx, now)
    73  	originalLp := tng.engine.LiquidityProvisionByPartyID(party)
    74  
    75  	require.NotNil(t, originalLp)
    76  	require.EqualValues(t, 1, originalLp.Version)
    77  
    78  	lpa, _ := types.LiquidityProvisionAmendmentFromProto(&commandspb.LiquidityProvisionAmendment{
    79  		MarketId:         market,
    80  		CommitmentAmount: "100000",
    81  		Fee:              "0.8",
    82  		Reference:        "ref-lp-submission-1",
    83  	})
    84  	// now we can do a OK can amend
    85  	assert.NoError(t, tng.engine.CanAmend(lpa, party, true))
    86  
    87  	_, err = tng.engine.AmendLiquidityProvision(ctx, lpa, party, true)
    88  	assert.NoError(t, err)
    89  
    90  	// first validate that the amendment is pending
    91  	pendingLp := tng.engine.PendingProvisionByPartyID(party)
    92  
    93  	assert.Equal(t, lpa.CommitmentAmount.String(), pendingLp.CommitmentAmount.String())
    94  	assert.Equal(t, lpa.Fee.String(), pendingLp.Fee.String())
    95  
    96  	lp := tng.engine.LiquidityProvisionByPartyID(party)
    97  	assert.Equal(t, originalLp.CommitmentAmount.String(), lp.CommitmentAmount.String())
    98  	assert.Equal(t, originalLp.Fee.String(), lp.Fee.String())
    99  	assert.Equal(t, originalLp.Version, lp.Version)
   100  
   101  	// amendment should take place at the start of new epoch
   102  	tng.engine.ResetSLAEpoch(now, zero, zero, zeroD)
   103  	tng.engine.ApplyPendingProvisions(ctx, now)
   104  
   105  	lp = tng.engine.LiquidityProvisionByPartyID(party)
   106  	assert.Equal(t, lpa.CommitmentAmount.String(), lp.CommitmentAmount.String())
   107  	assert.Equal(t, lpa.Fee.String(), lp.Fee.String())
   108  	assert.EqualValues(t, 2, lp.Version)
   109  
   110  	// previously, this tested for an empty string, this is impossible now with the decimal type
   111  	// so let's check for negatives instead
   112  	lpa.Fee = num.DecimalFromFloat(-1)
   113  	assert.EqualError(t,
   114  		tng.engine.CanAmend(lpa, party, true),
   115  		"invalid liquidity provision fee",
   116  	)
   117  }
   118  
   119  func TestCancelTroughAmendmentDuringOpeningAuction(t *testing.T) {
   120  	var (
   121  		party = "party-1"
   122  		ctx   = context.Background()
   123  		tng   = newTestEngine(t)
   124  	)
   125  	defer tng.ctrl.Finish()
   126  
   127  	assert.EqualError(t,
   128  		tng.engine.CanAmend(nil, party, true),
   129  		liquidity.ErrPartyHaveNoLiquidityProvision.Error(),
   130  	)
   131  
   132  	lps, _ := types.LiquidityProvisionSubmissionFromProto(&commandspb.LiquidityProvisionSubmission{
   133  		MarketId:         market,
   134  		CommitmentAmount: "10000",
   135  		Fee:              "0.5",
   136  		Reference:        "ref-lp-submission-1",
   137  	})
   138  
   139  	idgen := idgeneration.New(crypto.RandomHash())
   140  	// initially submit our provision to be amended, does not matter what's in
   141  	tng.broker.EXPECT().Send(gomock.Any()).AnyTimes()
   142  	// set opening auction
   143  	tng.auctionState.EXPECT().InAuction().Return(true).AnyTimes()
   144  	tng.auctionState.EXPECT().IsOpeningAuction().Return(true).AnyTimes()
   145  
   146  	applied, err := tng.engine.SubmitLiquidityProvision(ctx, lps, party, idgen)
   147  	assert.NoError(t, err)
   148  	assert.True(t, applied)
   149  
   150  	// amend to zero - cancel
   151  	lpa, _ := types.LiquidityProvisionAmendmentFromProto(&commandspb.LiquidityProvisionAmendment{
   152  		MarketId:         market,
   153  		CommitmentAmount: "0",
   154  		Fee:              "0",
   155  	})
   156  
   157  	applied, err = tng.engine.AmendLiquidityProvision(ctx, lpa, party, true)
   158  	assert.NoError(t, err)
   159  	assert.True(t, applied)
   160  
   161  	// should not be in pending
   162  	pendingLp := tng.engine.PendingProvisionByPartyID(party)
   163  	assert.Nil(t, pendingLp)
   164  
   165  	// should not be in current
   166  	currentLp := tng.engine.LiquidityProvisionByPartyID(party)
   167  	assert.Nil(t, currentLp)
   168  
   169  	// LP is able to submit again - since they cancelled before
   170  	applied, err = tng.engine.SubmitLiquidityProvision(ctx, lps, party, idgen)
   171  	assert.NoError(t, err)
   172  	assert.True(t, applied)
   173  
   174  	lp := tng.engine.LiquidityProvisionByPartyID(party)
   175  	assert.Equal(t, lps.CommitmentAmount.String(), lp.CommitmentAmount.String())
   176  	assert.Equal(t, lps.Fee.String(), lp.Fee.String())
   177  	assert.EqualValues(t, 1, lp.Version)
   178  }