Skip to content

Commit

Permalink
fix: verify parties can afford the spot trade they're trying to do
Browse files Browse the repository at this point in the history
  • Loading branch information
ze97286 committed Apr 25, 2024
1 parent 71b56e4 commit 9b9e5bc
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
- [11161](https://github.com/vegaprotocol/vega/issues/11161) - Add validation for time in force GFA in stop order submission.
- [11177](https://github.com/vegaprotocol/vega/issues/11177) - Adjust the formulas for reduced position to the spec update and fix handling of closed out position.
- [11193](https://github.com/vegaprotocol/vega/issues/11193) - Fix loading of liquidation strategy from proto with missing data.
- [11200](https://github.com/vegaprotocol/vega/issues/11200) - Make sure a party can afford the trades before they are submitted to the book.

## 0.75.0

Expand Down
43 changes: 43 additions & 0 deletions core/execution/spot/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,35 @@ func (m *Market) submitOrder(ctx context.Context, order *types.Order) (*types.Or
return orderConf, orderUpdates, err
}

func (m *Market) canCoverTradesAndFees(party string, partySide types.Side, trades []*types.Trade) error {
// check that the party can afford the traded amount + fees
if partySide == types.SideBuy {
totalTraded := num.UintZero()
for _, t := range trades {
fees, err := m.calculateFeesForTrades([]*types.Trade{t})
if err != nil {
m.log.Panic("failed to calculate fees for trade", logging.Trade(t))
}
size := num.NewUint(t.Size)
totalTraded.AddSum(size.Mul(size, t.Price), fees.TotalFeesAmountPerParty()[party])
}
totalTraded, _ = num.UintFromDecimal(totalTraded.ToDecimal().Div(m.positionFactor))
if err := m.collateral.PartyHasSufficientBalance(m.quoteAsset, party, totalTraded); err != nil {
return err
}
} else {
sizeTraded := uint64(0)
for _, t := range trades {
sizeTraded += t.Size
}
totalTraded := scaleBaseQuantityToAssetDP(sizeTraded, m.baseFactor)
if err := m.collateral.PartyHasSufficientBalance(m.baseAsset, party, totalTraded); err != nil {
return err
}
}
return nil
}

// submitValidatedOrder submits a new order.
func (m *Market) submitValidatedOrder(ctx context.Context, order *types.Order) (*types.OrderConfirmation, []*types.Order, error) {
isPegged := order.PeggedOrder != nil
Expand Down Expand Up @@ -1441,6 +1470,13 @@ func (m *Market) submitValidatedOrder(ctx context.Context, order *types.Order) (
// not be an issue
}

// check that the party can afford the trade and fees
if trades != nil {
if err := m.canCoverTradesAndFees(order.Party, order.Side, trades); err != nil {
return nil, nil, m.unregisterAndReject(ctx, order, err)
}
}

// if an auction is ongoing and the order is pegged, park it and return
if m.as.InAuction() && isPegged {
if isPegged {
Expand Down Expand Up @@ -2398,6 +2434,13 @@ func (m *Market) orderCancelReplace(ctx context.Context, existingOrder, newOrder
return nil, nil, errors.New("couldn't insert order in book")
}

// check that the party can afford the trade - if not return error and ignore the update
if trades != nil {
if err := m.canCoverTradesAndFees(newOrder.Party, newOrder.Side, trades); err != nil {
return nil, nil, err
}
}

// "hot-swap" of the orders
conf, err = m.matching.ReplaceOrder(existingOrder, newOrder)
if err != nil {
Expand Down

0 comments on commit 9b9e5bc

Please sign in to comment.