code.vegaprotocol.io/vega@v0.79.0/core/execution/engine_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 execution_test 17 18 import ( 19 "context" 20 "encoding/hex" 21 "fmt" 22 "testing" 23 "time" 24 25 "code.vegaprotocol.io/vega/core/assets" 26 dstypes "code.vegaprotocol.io/vega/core/datasource/common" 27 "code.vegaprotocol.io/vega/core/datasource/spec" 28 "code.vegaprotocol.io/vega/core/events" 29 "code.vegaprotocol.io/vega/core/types" 30 vgcontext "code.vegaprotocol.io/vega/libs/context" 31 "code.vegaprotocol.io/vega/libs/num" 32 33 "github.com/golang/mock/gomock" 34 "github.com/stretchr/testify/require" 35 ) 36 37 func TestMarketSuccession(t *testing.T) { 38 exec := getMockedEngine(t) 39 exec.timeSvc.EXPECT().GetTimeNow().AnyTimes().Return(time.Now()) 40 exec.OnSuccessorMarketTimeWindowUpdate(context.Background(), 100*time.Second) 41 defer exec.ctrl.Finish() 42 knownAssets := map[string]*assets.Asset{} 43 mkt := getMarketConfig() 44 mkt.ID = "parentID" 45 // sendCount, batchCount := 0, 0 46 ctx := vgcontext.WithTraceID(context.Background(), hex.EncodeToString([]byte("0deadbeef"))) 47 // for now, we don't care about this much 48 // exec.epoch.EXPECT().NotifyOnEpoch(gomock.Any(), gomock.Any()).AnyTimes() 49 exec.asset.EXPECT().Get(gomock.Any()).AnyTimes().DoAndReturn(func(asset string) (*assets.Asset, error) { 50 a, ok := knownAssets[asset] 51 if !ok { 52 a = NewAssetStub(asset, 0) 53 knownAssets[asset] = a 54 } 55 if a == nil { 56 return nil, fmt.Errorf("unknown asset") 57 } 58 return a, nil 59 }) 60 // this is to propose the parent market and the 2 successors, and starting the opening auction for the eventual successor 61 seen := false 62 exec.broker.EXPECT().Send(gomock.Any()).AnyTimes().Do(func(e events.Event) { 63 if e.Type() == events.MarketUpdatedEvent { 64 seen = true 65 } 66 }) 67 exec.broker.EXPECT().SendBatch(gomock.Any()).AnyTimes() 68 exec.collateral.EXPECT().GetAssetQuantum("Ethereum/Ether").AnyTimes().Return(num.DecimalFromInt64(1), nil) 69 exec.collateral.EXPECT().AssetExists(gomock.Any()).AnyTimes().Return(true) 70 exec.collateral.EXPECT().CreateMarketAccounts(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 71 exec.oracle.EXPECT().Subscribe(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(spec.SubscriptionID(0), func(_ context.Context, _ spec.SubscriptionID) {}, nil) 72 exec.statevar.EXPECT().RegisterStateVariable(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 73 exec.statevar.EXPECT().NewEvent(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 74 75 // create parent market 76 err := exec.SubmitMarket(ctx, mkt, "", time.Now()) 77 require.NoError(t, err) 78 79 // create successors 80 child1 := getMarketConfig() 81 child1.ParentMarketID = mkt.ID 82 child1.ID = "child1" 83 child1.InsurancePoolFraction = num.DecimalFromFloat(.5) 84 child1.State = types.MarketStateProposed 85 86 child2 := getMarketConfig() 87 child2.ParentMarketID = mkt.ID 88 child2.ID = "child2" 89 child2.InsurancePoolFraction = num.DecimalFromFloat(.33) 90 child2.State = types.MarketStateActive 91 // submit successor markets 92 err = exec.SubmitMarket(ctx, child1, "", time.Now()) 93 require.NoError(t, err) 94 err = exec.SubmitMarket(ctx, child2, "", time.Now()) 95 require.NoError(t, err) 96 97 // when enacting a successor market, a lot of stuff happens: 98 99 // Transfer insurance pool fraction 100 acc := &types.Account{ 101 Balance: num.UintZero(), 102 } 103 exec.collateral.EXPECT().GetMarketLiquidityFeeAccount(gomock.Any(), gomock.Any()).AnyTimes().Return(acc, nil) 104 // exec.collateral.EXPECT().SuccessorInsuranceFraction(ctx, child1.ID, child1.ParentMarketID, gomock.Any(), child1.InsurancePoolFraction).Times(1).Return(&types.LedgerMovement{}) 105 // which in turn emits an event with ledger movements 106 // we get the parent market state to pass in the ELS and stuff: 107 exec.collateral.EXPECT().GetInsurancePoolBalance(child1.ParentMarketID, gomock.Any()).AnyTimes().Return(num.NewUint(100), true) // the balance doesn't matter for this test 108 exec.collateral.EXPECT().GetInsurancePoolBalance(child1.ID, gomock.Any()).AnyTimes().Return(num.NewUint(50), true) // the balance doesn't matter for this test 109 exec.collateral.EXPECT().GetInsurancePoolBalance(child2.ID, gomock.Any()).AnyTimes().Return(num.NewUint(50), true) // the balance doesn't matter for this test 110 // Any accounts associated with the now rejected successor market will be removed 111 // exec.collateral.EXPECT().ClearMarket(ctx, child2.ID, gomock.Any(), gomock.Any()).Times(1).Return(nil, nil) 112 // statevars associated with the rejected successor market are unregistered 113 exec.statevar.EXPECT().UnregisterStateVariable(gomock.Any(), child2.ID).AnyTimes() 114 // the other succesor markets are rejected and removed, which emits market update events 115 // set parent market to be settled 116 err = exec.StartOpeningAuction(ctx, child1.ID) 117 require.NoError(t, err) 118 mkt.State = types.MarketStateSettled 119 child1.State = types.MarketStateProposed 120 // start opening auction for the successor market 121 err = exec.SucceedMarket(ctx, child1.ID, child1.ParentMarketID) 122 require.NoError(t, err) 123 exec.OnTick(ctx, time.Now()) 124 require.True(t, seen) 125 } 126 127 func TestUpdateMarginUpdate(t *testing.T) { 128 engine, ctrl := createEngine(t) 129 defer ctrl.Finish() 130 131 require.Equal(t, types.ErrInvalidMarketID, engine.UpdateMarginMode(context.Background(), "zohar", "unknown", types.MarginModeIsolatedMargin, num.DecimalOne())) 132 133 pubKey := &dstypes.SignerPubKey{ 134 PubKey: &dstypes.PubKey{ 135 Key: "0xDEADBEEF", 136 }, 137 } 138 mkt := newMarket("market-id", pubKey) 139 mkt.LinearSlippageFactor = num.DecimalFromFloat(0.1) 140 require.NoError(t, engine.SubmitMarket(context.Background(), mkt, "zohar", time.Now())) 141 142 // rfShort, rfLong = 1 143 require.Equal(t, "margin factor (0.5) must be greater than max(riskFactorLong (1), riskFactorShort (1)) + linearSlippageFactor (0.1)", engine.UpdateMarginMode(context.Background(), "zohar", "market-id", types.MarginModeIsolatedMargin, num.DecimalFromFloat(0.5)).Error()) 144 require.Equal(t, "margin factor (1.05) must be greater than max(riskFactorLong (1), riskFactorShort (1)) + linearSlippageFactor (0.1)", engine.UpdateMarginMode(context.Background(), "zohar", "market-id", types.MarginModeIsolatedMargin, num.DecimalFromFloat(1.05)).Error()) 145 }