diff --git a/plugin/evm/limit_order.go b/plugin/evm/limit_order.go index 8c6b265da3..ea77cc6384 100644 --- a/plugin/evm/limit_order.go +++ b/plugin/evm/limit_order.go @@ -72,6 +72,7 @@ func NewLimitOrderProcesser(ctx *snow.Context, txPool *txpool.TxPool, shutdownCh // need to register the types for gob encoding because memory DB has an interface field(ContractOrder) gob.Register(&orderbook.LimitOrder{}) + gob.Register(&orderbook.LimitOrderV2{}) gob.Register(&orderbook.IOCOrder{}) return &limitOrderProcesser{ ctx: ctx, @@ -231,14 +232,17 @@ func (lop *limitOrderProcesser) listenAndStoreLimitOrderTransactions() { // If n is the block at which snapshot should be saved(n is multiple of [snapshotInterval]), save the snapshot // when logs of block number >= n + 1 are received before applying them in memory db - blockNumberFloor := ((blockNumber - 1) / snapshotInterval) * snapshotInterval + // snapshot should be saved at block number = blockNumber - 1 because Accepted logs + // have been applied in memory DB at this point + snapshotBlockNumber := blockNumber - 1 + blockNumberFloor := ((snapshotBlockNumber) / snapshotInterval) * snapshotInterval if blockNumberFloor > lop.snapshotSavedBlockNumber { - log.Info("Saving memory DB snapshot", "blockNumber", blockNumber, "blockNumberFloor", blockNumberFloor) - floorBlock := lop.blockChain.GetBlockByNumber(blockNumberFloor) - lop.memoryDb.Accept(blockNumberFloor, floorBlock.Timestamp()) - err := lop.saveMemoryDBSnapshot(big.NewInt(int64(blockNumberFloor))) + log.Info("Saving memory DB snapshot", "snapshotBlockNumber", snapshotBlockNumber, "current blockNumber", blockNumber, "blockNumberFloor", blockNumberFloor) + snapshotBlock := lop.blockChain.GetBlockByNumber(snapshotBlockNumber) + lop.memoryDb.Accept(snapshotBlockNumber, snapshotBlock.Timestamp()) + err := lop.saveMemoryDBSnapshot(big.NewInt(int64(snapshotBlockNumber))) if err != nil { - log.Error("Error in saving memory DB snapshot", "err", err) + log.Error("Error in saving memory DB snapshot", "err", err, "snapshotBlockNumber", snapshotBlockNumber, "current blockNumber", blockNumber, "blockNumberFloor", blockNumberFloor) } } diff --git a/plugin/evm/orderbook/memory_database.go b/plugin/evm/orderbook/memory_database.go index f4b1e28fe9..3c5aba21e7 100644 --- a/plugin/evm/orderbook/memory_database.go +++ b/plugin/evm/orderbook/memory_database.go @@ -264,6 +264,8 @@ func (db *InMemoryDatabase) LoadFromSnapshot(snapshot Snapshot) error { db.TraderMap = snapshot.Data.TraderMap db.LastPrice = snapshot.Data.LastPrice db.NextFundingTime = snapshot.Data.NextFundingTime + db.NextSamplePITime = snapshot.Data.NextSamplePITime + db.CumulativePremiumFraction = snapshot.Data.CumulativePremiumFraction return nil } @@ -753,7 +755,8 @@ func (db *InMemoryDatabase) GetNaughtyTraders(oraclePrices map[Market]*big.Int, } // has orders that might be cancellable availableMargin := getAvailableMargin(trader, pendingFunding, oraclePrices, db.LastPrice, db.configService.getMinAllowableMargin(), markets) - if availableMargin.Cmp(big.NewInt(0)) == -1 { + // availableMargin := getAvailableMarginWithDebugInfo(addr, trader, pendingFunding, oraclePrices, db.LastPrice, db.configService.getMinAllowableMargin(), markets) + if availableMargin.Sign() == -1 { foundCancellableOrders := db.determineOrdersToCancel(addr, trader, availableMargin, oraclePrices, ordersToCancel) if foundCancellableOrders { log.Info("negative available margin", "trader", addr.String(), "availableMargin", prettifyScaledBigInt(availableMargin, 6)) @@ -929,18 +932,30 @@ func getBlankTrader() *Trader { } func getAvailableMargin(trader *Trader, pendingFunding *big.Int, oraclePrices map[Market]*big.Int, lastPrices map[Market]*big.Int, minAllowableMargin *big.Int, markets []Market) *big.Int { - // log.Info("in getAvailableMargin", "trader", trader, "pendingFunding", pendingFunding, "oraclePrices", oraclePrices, "lastPrices", lastPrices) margin := new(big.Int).Sub(getNormalisedMargin(trader), pendingFunding) notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(trader, margin, Min_Allowable_Margin, oraclePrices, lastPrices, markets) utilisedMargin := divideByBasePrecision(new(big.Int).Mul(notionalPosition, minAllowableMargin)) - // print margin, notionalPosition, unrealizePnL, utilisedMargin - // log.Info("stats", "margin", margin, "notionalPosition", notionalPosition, "unrealizePnL", unrealizePnL, "utilisedMargin", utilisedMargin, "Reserved", trader.Margin.Reserved) return new(big.Int).Sub( new(big.Int).Add(margin, unrealizePnL), new(big.Int).Add(utilisedMargin, trader.Margin.Reserved), ) } +func getAvailableMarginWithDebugInfo(addr common.Address, trader *Trader, pendingFunding *big.Int, oraclePrices map[Market]*big.Int, lastPrices map[Market]*big.Int, minAllowableMargin *big.Int, markets []Market) *big.Int { + margin := new(big.Int).Sub(getNormalisedMargin(trader), pendingFunding) + notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(trader, margin, Min_Allowable_Margin, oraclePrices, lastPrices, markets) + utilisedMargin := divideByBasePrecision(new(big.Int).Mul(notionalPosition, minAllowableMargin)) + availableMargin := new(big.Int).Sub( + new(big.Int).Add(margin, unrealizePnL), + new(big.Int).Add(utilisedMargin, trader.Margin.Reserved), + ) + if availableMargin.Sign() == -1 { + log.Info("availableMargin < 0", "addr", addr.String(), "pendingFunding", pendingFunding, "margin", margin, "notionalPosition", notionalPosition, "unrealizePnL", unrealizePnL, "utilisedMargin", utilisedMargin, "Reserved", trader.Margin.Reserved) + log.Info("prices", "oraclePrices", oraclePrices, "lastPrices", lastPrices) + } + return availableMargin +} + // deepCopyOrder deep copies the LimitOrder struct func deepCopyOrder(order *Order) Order { lifecycleList := &order.LifecycleList diff --git a/plugin/evm/orderbook/tx_processor.go b/plugin/evm/orderbook/tx_processor.go index 707ff98006..be135e9f3d 100644 --- a/plugin/evm/orderbook/tx_processor.go +++ b/plugin/evm/orderbook/tx_processor.go @@ -3,7 +3,7 @@ package orderbook import ( "context" "crypto/ecdsa" - "encoding/hex" + // "encoding/hex" "errors" "fmt" "math/big" @@ -139,7 +139,7 @@ func (lotp *limitOrderTxProcessor) ExecuteMatchedOrdersTx(longOrder Order, short return err } - log.Info("ExecuteMatchedOrdersTx", "orders[0]", hex.EncodeToString(orders[0]), "orders[1]", hex.EncodeToString(orders[1]), "fillAmount", prettifyScaledBigInt(fillAmount, 18)) + // log.Info("ExecuteMatchedOrdersTx", "orders[0]", hex.EncodeToString(orders[0]), "orders[1]", hex.EncodeToString(orders[1]), "fillAmount", prettifyScaledBigInt(fillAmount, 18)) txHash, err := lotp.executeLocalTx(lotp.orderBookContractAddress, lotp.orderBookABI, "executeMatchedOrders", orders, fillAmount) log.Info("ExecuteMatchedOrdersTx", "LongOrder", longOrder, "ShortOrder", shortOrder, "fillAmount", prettifyScaledBigInt(fillAmount, 18), "txHash", txHash.String(), "err", err) return err diff --git a/precompile/contracts/bibliophile/api.go b/precompile/contracts/bibliophile/api.go index 012aecfd92..64f1fa9658 100644 --- a/precompile/contracts/bibliophile/api.go +++ b/precompile/contracts/bibliophile/api.go @@ -2,6 +2,7 @@ package bibliophile import ( "math/big" + "time" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ethereum/go-ethereum/common" @@ -28,7 +29,7 @@ func GetClearingHouseVariables(stateDB contract.StateDB, trader common.Address) Trader: trader, IncludeFundingPayments: false, Mode: 0, - }, big.NewInt(0)) + }, big.NewInt(time.Now().Unix())) totalFunding := GetTotalFunding(stateDB, &trader) positionSizes := getPosSizes(stateDB, &trader) underlyingPrices := GetUnderlyingPrices(stateDB) @@ -118,7 +119,7 @@ func GetAMMVariables(stateDB contract.StateDB, ammAddress common.Address, ammInd minAllowableMargin := GetMinAllowableMargin(stateDB) takerFee := GetTakerFee(stateDB) totalMargin := GetNormalizedMargin(stateDB, trader) - availableMargin := GetAvailableMargin(stateDB, trader) + availableMargin := GetAvailableMargin(stateDB, trader, big.NewInt(time.Now().Unix())) reduceOnlyAmount := getReduceOnlyAmount(stateDB, trader, big.NewInt(ammIndex)) longOpenOrdersAmount := getLongOpenOrdersAmount(stateDB, trader, big.NewInt(ammIndex)) shortOpenOrdersAmount := getShortOpenOrdersAmount(stateDB, trader, big.NewInt(ammIndex)) diff --git a/precompile/contracts/bibliophile/client.go b/precompile/contracts/bibliophile/client.go index 107f33904d..7869645ea3 100644 --- a/precompile/contracts/bibliophile/client.go +++ b/precompile/contracts/bibliophile/client.go @@ -22,6 +22,7 @@ type BibliophileClient interface { GetShortOpenOrdersAmount(trader common.Address, ammIndex *big.Int) *big.Int GetReduceOnlyAmount(trader common.Address, ammIndex *big.Int) *big.Int IsTradingAuthority(trader, senderOrSigner common.Address) bool + IsValidator(senderOrSigner common.Address) bool // Limit Order GetBlockPlaced(orderHash [32]byte) *big.Int GetOrderFilledAmount(orderHash [32]byte) *big.Int @@ -118,6 +119,10 @@ func (b *bibliophileClient) IsTradingAuthority(trader, senderOrSigner common.Add return IsTradingAuthority(b.accessibleState.GetStateDB(), trader, senderOrSigner) } +func (b *bibliophileClient) IsValidator(senderOrSigner common.Address) bool { + return IsValidator(b.accessibleState.GetStateDB(), senderOrSigner) +} + func (b *bibliophileClient) IOC_GetExpirationCap() *big.Int { return iocGetExpirationCap(b.accessibleState.GetStateDB()) } @@ -171,5 +176,6 @@ func (b *bibliophileClient) GetReduceOnlyAmount(trader common.Address, ammIndex } func (b *bibliophileClient) GetAvailableMargin(trader common.Address) *big.Int { - return GetAvailableMargin(b.accessibleState.GetStateDB(), trader) + blockTimestamp := new(big.Int).SetUint64(b.accessibleState.GetBlockContext().Timestamp()) + return GetAvailableMargin(b.accessibleState.GetStateDB(), trader, blockTimestamp) } diff --git a/precompile/contracts/bibliophile/client_mock.go b/precompile/contracts/bibliophile/client_mock.go index 6685b8ba77..e14dfebfee 100644 --- a/precompile/contracts/bibliophile/client_mock.go +++ b/precompile/contracts/bibliophile/client_mock.go @@ -432,15 +432,29 @@ func (mr *MockBibliophileClientMockRecorder) IOC_GetOrderStatus(orderHash interf } // IsTradingAuthority mocks base method. -func (m *MockBibliophileClient) IsTradingAuthority(senderOrSigner, trader common.Address) bool { +func (m *MockBibliophileClient) IsTradingAuthority(trader, senderOrSigner common.Address) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsTradingAuthority", senderOrSigner, trader) + ret := m.ctrl.Call(m, "IsTradingAuthority", trader, senderOrSigner) ret0, _ := ret[0].(bool) return ret0 } // IsTradingAuthority indicates an expected call of IsTradingAuthority. -func (mr *MockBibliophileClientMockRecorder) IsTradingAuthority(senderOrSigner, trader interface{}) *gomock.Call { +func (mr *MockBibliophileClientMockRecorder) IsTradingAuthority(trader, senderOrSigner interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTradingAuthority", reflect.TypeOf((*MockBibliophileClient)(nil).IsTradingAuthority), senderOrSigner, trader) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTradingAuthority", reflect.TypeOf((*MockBibliophileClient)(nil).IsTradingAuthority), trader, senderOrSigner) +} + +// IsValidator mocks base method. +func (m *MockBibliophileClient) IsValidator(senderOrSigner common.Address) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsValidator", senderOrSigner) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsValidator indicates an expected call of IsValidator. +func (mr *MockBibliophileClientMockRecorder) IsValidator(senderOrSigner interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsValidator", reflect.TypeOf((*MockBibliophileClient)(nil).IsValidator), senderOrSigner) } diff --git a/precompile/contracts/bibliophile/margin_account.go b/precompile/contracts/bibliophile/margin_account.go index c44a8f97a1..0e89d107e3 100644 --- a/precompile/contracts/bibliophile/margin_account.go +++ b/precompile/contracts/bibliophile/margin_account.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + // "github.com/ethereum/go-ethereum/log" ) const ( @@ -32,13 +33,22 @@ func getReservedMargin(stateDB contract.StateDB, trader common.Address) *big.Int return stateDB.GetState(common.HexToAddress(MARGIN_ACCOUNT_GENESIS_ADDRESS), common.BytesToHash(baseMappingHash)).Big() } -func GetAvailableMargin(stateDB contract.StateDB, trader common.Address) *big.Int { +// Monday, 4 September 2023 10:05:00 +var V5ActivationDate *big.Int = new(big.Int).SetInt64(1693821900) + +func GetAvailableMargin(stateDB contract.StateDB, trader common.Address, blockTimestamp *big.Int) *big.Int { includeFundingPayment := true mode := uint8(1) // Min_Allowable_Margin - output := GetNotionalPositionAndMargin(stateDB, &GetNotionalPositionAndMarginInput{Trader: trader, IncludeFundingPayments: includeFundingPayment, Mode: mode}, nil) + var output GetNotionalPositionAndMarginOutput + if blockTimestamp != nil && blockTimestamp.Cmp(V5ActivationDate) == 1 { + output = GetNotionalPositionAndMargin(stateDB, &GetNotionalPositionAndMarginInput{Trader: trader, IncludeFundingPayments: includeFundingPayment, Mode: mode}, blockTimestamp) + } else { + output = GetNotionalPositionAndMargin(stateDB, &GetNotionalPositionAndMarginInput{Trader: trader, IncludeFundingPayments: includeFundingPayment, Mode: mode}, nil) + } notionalPostion := output.NotionalPosition margin := output.Margin utitlizedMargin := divide1e6(big.NewInt(0).Mul(notionalPostion, GetMinAllowableMargin(stateDB))) reservedMargin := getReservedMargin(stateDB, trader) + // log.Info("GetAvailableMargin", "trader", trader, "notionalPostion", notionalPostion, "margin", margin, "utitlizedMargin", utitlizedMargin, "reservedMargin", reservedMargin) return big.NewInt(0).Sub(big.NewInt(0).Sub(margin, utitlizedMargin), reservedMargin) } diff --git a/precompile/contracts/bibliophile/orderbook.go b/precompile/contracts/bibliophile/orderbook.go index 607174a7b7..c879995f30 100644 --- a/precompile/contracts/bibliophile/orderbook.go +++ b/precompile/contracts/bibliophile/orderbook.go @@ -14,6 +14,7 @@ import ( const ( ORDERBOOK_GENESIS_ADDRESS = "0x0300000000000000000000000000000000000000" ORDER_INFO_SLOT int64 = 53 + IS_VALIDATOR_SLOT int64 = 54 REDUCE_ONLY_AMOUNT_SLOT int64 = 55 IS_TRADING_AUTHORITY_SLOT int64 = 61 LONG_OPEN_ORDERS_SLOT int64 = 65 @@ -79,6 +80,11 @@ func IsTradingAuthority(stateDB contract.StateDB, trader, senderOrSigner common. return stateDB.GetState(common.HexToAddress(ORDERBOOK_GENESIS_ADDRESS), common.BytesToHash(tradingAuthorityMappingSlot)).Big().Cmp(big.NewInt(1)) == 0 } +func IsValidator(stateDB contract.StateDB, senderOrSigner common.Address) bool { + isValidatorMappingSlot := crypto.Keccak256(append(common.LeftPadBytes(senderOrSigner.Bytes(), 32), common.LeftPadBytes(big.NewInt(IS_VALIDATOR_SLOT).Bytes(), 32)...)) + return stateDB.GetState(common.HexToAddress(ORDERBOOK_GENESIS_ADDRESS), common.BytesToHash(isValidatorMappingSlot)).Big().Cmp(big.NewInt(1)) == 0 +} + // Business Logic func ValidateOrdersAndDetermineFillPrice(stateDB contract.StateDB, inputStruct *ValidateOrdersAndDetermineFillPriceInput) (*ValidateOrdersAndDetermineFillPriceOutput, error) { diff --git a/precompile/contracts/juror/contract.go b/precompile/contracts/juror/contract.go index f40b4386f0..be92b10d3d 100644 --- a/precompile/contracts/juror/contract.go +++ b/precompile/contracts/juror/contract.go @@ -5,7 +5,6 @@ package juror import ( - "encoding/hex" "errors" "fmt" "math/big" @@ -442,7 +441,7 @@ func validateCancelLimitOrder(accessibleState contract.AccessibleState, caller c } // CUSTOM CODE STARTS HERE bibliophile := bibliophile.NewBibliophileClient(accessibleState) - output := ValidateCancelLimitOrderV2(bibliophile, &inputStruct) + output := ValidateCancelLimitOrderV2(bibliophile, &inputStruct, new(big.Int).SetUint64(accessibleState.GetBlockContext().Timestamp())) packedOutput, err := PackValidateCancelLimitOrderOutput(*output) if err != nil { return nil, remainingGas, err @@ -541,7 +540,6 @@ func validateOrdersAndDetermineFillPrice(accessibleState contract.AccessibleStat return nil, remainingGas, err } - log.Info("validateOrdersAndDetermineFillPrice", "orders[0]", hex.EncodeToString(inputStruct.Data[0]), "orders[1]", hex.EncodeToString(inputStruct.Data[1]), "fillAmount", inputStruct.FillAmount) // CUSTOM CODE STARTS HERE bibliophile := bibliophile.NewBibliophileClient(accessibleState) output, err := ValidateOrdersAndDetermineFillPrice(bibliophile, &inputStruct) @@ -625,7 +623,7 @@ func PackValidatePlaceLimitOrder(inputStruct ValidatePlaceLimitOrderInput) ([]by func PackValidatePlaceLimitOrderOutput(outputStruct ValidatePlaceLimitOrderOutput) ([]byte, error) { // @todo orderHash looks ugly // lvl=info msg=validatePlaceLimitOrder outputStruct="{Errs: Orderhash:[163 9 195 151 255 44 17 22 177 218 216 139 75 238 217 56 226 244 244 41 106 243 100 63 204 145 170 96 95 106 252 157] Res:{ReserveAmount:+6015000 Amm:0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf}}" - log.Info("validatePlaceLimitOrder", "outputStruct", outputStruct) + // log.Info("validatePlaceLimitOrder", "outputStruct", outputStruct) return JurorABI.PackOutput("validatePlaceLimitOrder", outputStruct.Errs, outputStruct.Orderhash, diff --git a/precompile/contracts/juror/contract_test.go b/precompile/contracts/juror/contract_test.go index 7aa7a0ff63..447cb2bf08 100644 --- a/precompile/contracts/juror/contract_test.go +++ b/precompile/contracts/juror/contract_test.go @@ -1636,14 +1636,14 @@ func TestValidateCancelLimitOrder(t *testing.T) { order := getOrder(ammIndex, trader, longBaseAssetQuantity, price, salt, reduceOnly, postOnly) input := getValidateCancelLimitOrderInput(order, sender, assertLowMargin) mockBibliophile.EXPECT().IsTradingAuthority(order.Trader, sender).Return(false).Times(1) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, ErrNoTradingAuthority.Error(), output.Err) }) t.Run("it returns error for a short order", func(t *testing.T) { order := getOrder(ammIndex, trader, shortBaseAssetQuantity, price, salt, reduceOnly, postOnly) input := getValidateCancelLimitOrderInput(order, sender, assertLowMargin) mockBibliophile.EXPECT().IsTradingAuthority(order.Trader, sender).Return(false).Times(1) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, ErrNoTradingAuthority.Error(), output.Err) }) }) @@ -1655,7 +1655,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { orderHash := getOrderV2Hash(longOrder) mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Invalid)).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Invalid", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1666,7 +1666,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { orderHash := getOrderV2Hash(shortOrder) mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Invalid)).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Invalid", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1679,7 +1679,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { orderHash := getOrderV2Hash(longOrder) mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Cancelled)).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Cancelled", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1690,7 +1690,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { orderHash := getOrderV2Hash(shortOrder) mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Cancelled)).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Cancelled", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1703,7 +1703,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { orderHash := getOrderV2Hash(longOrder) mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Filled)).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Filled", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1714,7 +1714,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { orderHash := getOrderV2Hash(shortOrder) mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Filled)).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Filled", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1734,7 +1734,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Placed)).Times(1) mockBibliophile.EXPECT().GetAvailableMargin(longOrder.Trader).Return(big.NewInt(0)).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Not Low Margin", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1747,7 +1747,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Placed)).Times(1) mockBibliophile.EXPECT().GetAvailableMargin(shortOrder.Trader).Return(big.NewInt(0)).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Not Low Margin", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) @@ -1764,7 +1764,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Placed)).Times(1) mockBibliophile.EXPECT().GetAvailableMargin(longOrder.Trader).Return(newMargin).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Not Low Margin", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1777,7 +1777,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetOrderStatus(orderHash).Return(int64(Placed)).Times(1) mockBibliophile.EXPECT().GetAvailableMargin(shortOrder.Trader).Return(newMargin).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "Not Low Margin", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, common.Address{}, output.Res.Amm) @@ -1797,7 +1797,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(longOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1813,7 +1813,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(shortOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1832,7 +1832,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(longOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1850,7 +1850,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(shortOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1872,7 +1872,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(longOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1887,7 +1887,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(shortOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1905,7 +1905,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(longOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(longOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) @@ -1922,7 +1922,7 @@ func TestValidateCancelLimitOrder(t *testing.T) { mockBibliophile.EXPECT().GetMarketAddressFromMarketID(shortOrder.AmmIndex.Int64()).Return(ammAddress).Times(1) input := getValidateCancelLimitOrderInput(shortOrder, trader, assertLowMargin) - output := ValidateCancelLimitOrderV2(mockBibliophile, &input) + output := ValidateCancelLimitOrderV2(mockBibliophile, &input, nil) assert.Equal(t, "", output.Err) assert.Equal(t, orderHash, common.BytesToHash(output.OrderHash[:])) assert.Equal(t, ammAddress, output.Res.Amm) diff --git a/precompile/contracts/juror/logic.go b/precompile/contracts/juror/logic.go index 64c7a317a2..6abd3a6df5 100644 --- a/precompile/contracts/juror/logic.go +++ b/precompile/contracts/juror/logic.go @@ -10,7 +10,6 @@ import ( "github.com/ava-labs/subnet-evm/plugin/evm/orderbook" b "github.com/ava-labs/subnet-evm/precompile/contracts/bibliophile" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" ) type OrderType uint8 @@ -94,7 +93,6 @@ func ValidateOrdersAndDetermineFillPrice(bibliophile b.BibliophileClient, inputS } decodeStep0, err := decodeTypeAndEncodedOrder(inputStruct.Data[0]) - log.Info("decodeStep0", "decodeStep0", decodeStep0, "err", err) if err != nil { return nil, err } @@ -104,7 +102,6 @@ func ValidateOrdersAndDetermineFillPrice(bibliophile b.BibliophileClient, inputS } decodeStep1, err := decodeTypeAndEncodedOrder(inputStruct.Data[1]) - log.Info("decodeStep1", "decodeStep1", decodeStep1, "err", err) if err != nil { return nil, err } @@ -517,8 +514,8 @@ func GetBaseQuote(bibliophile b.BibliophileClient, ammAddress common.Address, qu } // Limit Orders V2 -func ValidateCancelLimitOrderV2(bibliophile b.BibliophileClient, inputStruct *ValidateCancelLimitOrderInput) *ValidateCancelLimitOrderOutput { - errorString, orderHash, ammAddress, unfilledAmount := validateCancelLimitOrderV2(bibliophile, inputStruct.Order, inputStruct.Trader, inputStruct.AssertLowMargin) +func ValidateCancelLimitOrderV2(bibliophile b.BibliophileClient, inputStruct *ValidateCancelLimitOrderInput, blockTimestamp *big.Int) *ValidateCancelLimitOrderOutput { + errorString, orderHash, ammAddress, unfilledAmount := validateCancelLimitOrderV2(bibliophile, inputStruct.Order, inputStruct.Trader, inputStruct.AssertLowMargin, blockTimestamp) return &ValidateCancelLimitOrderOutput{ Err: errorString, OrderHash: orderHash, @@ -529,12 +526,23 @@ func ValidateCancelLimitOrderV2(bibliophile b.BibliophileClient, inputStruct *Va } } -func validateCancelLimitOrderV2(bibliophile b.BibliophileClient, order ILimitOrderBookOrderV2, sender common.Address, assertLowMargin bool) (errorString string, orderHash [32]byte, ammAddress common.Address, unfilledAmount *big.Int) { +// Sunday, 3 September 2023 10:35:00 UTC +var V4ActivationDate *big.Int = new(big.Int).SetInt64(1693737300) + +func validateCancelLimitOrderV2(bibliophile b.BibliophileClient, order ILimitOrderBookOrderV2, sender common.Address, assertLowMargin bool, blockTimestamp *big.Int) (errorString string, orderHash [32]byte, ammAddress common.Address, unfilledAmount *big.Int) { unfilledAmount = big.NewInt(0) trader := order.Trader - if trader != sender && !bibliophile.IsTradingAuthority(trader, sender) { - errorString = ErrNoTradingAuthority.Error() - return + if blockTimestamp != nil && blockTimestamp.Cmp(V4ActivationDate) == 1 { + if (!assertLowMargin && trader != sender && !bibliophile.IsTradingAuthority(trader, sender)) || + (assertLowMargin && !bibliophile.IsValidator(sender)) { + errorString = ErrNoTradingAuthority.Error() + return + } + } else { + if trader != sender && !bibliophile.IsTradingAuthority(trader, sender) { + errorString = ErrNoTradingAuthority.Error() + return + } } orderHash, err := GetLimitOrderV2Hash(&order) if err != nil {