Skip to content

Commit

Permalink
chore: implement an allow list on market for the sell side
Browse files Browse the repository at this point in the history
Signed-off-by: Voltaire Chocolatine <q7mbqtQKGpsfaPAHKpHJ5Dgdg6at3YBQzmR@proton.me>
  • Loading branch information
voltaireChocolatine committed Oct 4, 2024
1 parent ac9993d commit 775d16a
Show file tree
Hide file tree
Showing 35 changed files with 3,754 additions and 3,053 deletions.
2 changes: 2 additions & 0 deletions core/execution/common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,6 @@ var (
// ErrSettlementDataOutOfRange is returned when a capped future receives settlement data that is outside of the acceptable range (either > max price, or neither 0 nor max for binary settlements).
ErrSettlementDataOutOfRange = errors.New("settlement data is outside of the price cap")
ErrAMMBoundsOutsidePriceCap = errors.New("an AMM bound is outside of the price cap")
// ErrSellOrderNotAllowed no sell orders are allowed in the current state.
ErrSellOrderNotAllowed = errors.New("sell order not allowed")
)
46 changes: 44 additions & 2 deletions core/execution/future/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ type Market struct {

amm *amm.Engine

fCap *types.FutureCap
capMax *num.Uint
fCap *types.FutureCap
capMax *num.Uint
allowedSellers map[string]struct{}
}

// NewMarket creates a new market using the market framework configuration and creates underlying engines.
Expand Down Expand Up @@ -321,6 +322,11 @@ func NewMarket(
mkt.LiquidationStrategy = liquidation.GetLegacyStrat()
}

allowedSellers := map[string]struct{}{}
for _, v := range mkt.AllowedSellers {
allowedSellers[v] = struct{}{}
}

marketType := mkt.MarketType()
market := &Market{
log: log,
Expand Down Expand Up @@ -366,6 +372,7 @@ func NewMarket(
banking: banking,
markPriceCalculator: common.NewCompositePriceCalculator(ctx, mkt.MarkPriceConfiguration, oracleEngine, timeService),
amm: ammEngine,
allowedSellers: allowedSellers,
}

le := liquidation.New(log, mkt.LiquidationStrategy, mkt.GetID(), broker, book, auctionState, timeService, positionEngine, pMonitor, market.amm)
Expand Down Expand Up @@ -642,6 +649,11 @@ func (m *Market) GetSettlementAsset() string {
func (m *Market) Update(ctx context.Context, config *types.Market, oracleEngine products.OracleEngine) error {
tickSizeChanged := config.TickSize.NEQ(m.mkt.TickSize)

clear(m.allowedSellers)
for _, v := range config.AllowedSellers {
m.allowedSellers[v] = struct{}{}
}

config.TradingMode = m.mkt.TradingMode
config.State = m.mkt.State
config.MarketTimestamps = m.mkt.MarketTimestamps
Expand Down Expand Up @@ -2148,6 +2160,16 @@ func (m *Market) SubmitStopOrdersWithIDGeneratorAndOrderIDs(
return nil, common.ErrTradingNotAllowed
}

if fallsBelow != nil && fallsBelow.OrderSubmission != nil && !m.canSubmitMaybeSell(fallsBelow.Party, fallsBelow.OrderSubmission.Side) {
rejectStopOrders(types.StopOrderRejectionSellOrderNotAllowed, fallsBelow, risesAbove)
return nil, common.ErrSellOrderNotAllowed
}

if risesAbove != nil && risesAbove.OrderSubmission != nil && !m.canSubmitMaybeSell(risesAbove.Party, risesAbove.OrderSubmission.Side) {
rejectStopOrders(types.StopOrderRejectionSellOrderNotAllowed, risesAbove, risesAbove)
return nil, common.ErrSellOrderNotAllowed
}

now := m.timeService.GetTimeNow()
orderCnt := 0
if fallsBelow != nil {
Expand Down Expand Up @@ -2404,6 +2426,13 @@ func (m *Market) SubmitOrderWithIDGeneratorAndOrderID(
return nil, common.ErrTradingNotAllowed
}

if !m.canSubmitMaybeSell(order.Party, order.Side) {
order.Status = types.OrderStatusRejected
order.Reason = types.OrderErrorSellOrderNotAllowed
m.broker.Send(events.NewOrderEvent(ctx, order))
return nil, common.ErrSellOrderNotAllowed
}

conf, orderUpdates, err := m.submitOrder(ctx, order)
if err != nil {
return nil, err
Expand Down Expand Up @@ -4987,6 +5016,19 @@ func (m *Market) canTrade() bool {
m.mkt.State == types.MarketStateSuspendedViaGovernance
}

func (m *Market) canSubmitMaybeSell(party string, side types.Side) bool {
// buy side
// or network party
// or no empty allowedSellers list
// are always fine
if len(m.allowedSellers) <= 0 || side == types.SideBuy || party == types.NetworkParty {
return true
}

_, isAllowed := m.allowedSellers[party]
return isAllowed
}

// cleanupOnReject remove all resources created while the
// market was on PREPARED state.
// we'll need to remove all accounts related to the market
Expand Down
7 changes: 7 additions & 0 deletions core/execution/future/market_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ func NewMarketFromSnapshot(
marketType := mkt.MarketType()

markPriceCalculator := common.NewCompositePriceCalculatorFromSnapshot(ctx, em.CurrentMarkPrice, timeService, oracleEngine, em.MarkPriceCalculator)

allowedSellers := map[string]struct{}{}
for _, v := range mkt.AllowedSellers {
allowedSellers[v] = struct{}{}
}

market := &Market{
log: log,
mkt: mkt,
Expand Down Expand Up @@ -266,6 +272,7 @@ func NewMarketFromSnapshot(
banking: banking,
markPriceCalculator: markPriceCalculator,
amm: ammEngine,
allowedSellers: allowedSellers,
}

markPriceCalculator.SetOraclePriceScalingFunc(market.scaleOracleData)
Expand Down
45 changes: 44 additions & 1 deletion core/execution/spot/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ type Market struct {
minDuration time.Duration
epoch types.Epoch

pap *ProtocolAutomatedPurchase
pap *ProtocolAutomatedPurchase
allowedSellers map[string]struct{}
}

// NewMarket creates a new market using the market framework configuration and creates underlying engines.
Expand Down Expand Up @@ -226,6 +227,12 @@ func NewMarket(
els := common.NewEquityShares(num.DecimalZero())
// @TODO pass in AMM
marketLiquidity := common.NewMarketLiquidity(log, liquidity, collateralEngine, broker, book, els, marketActivityTracker, feeEngine, common.SpotMarketType, mkt.ID, quoteAsset, priceFactor, mkt.LiquiditySLAParams.PriceRange, nil)

allowedSellers := map[string]struct{}{}
for _, v := range mkt.AllowedSellers {
allowedSellers[v] = struct{}{}
}

market := &Market{
log: log,
idgen: nil,
Expand Down Expand Up @@ -266,6 +273,7 @@ func NewMarket(
stopOrders: stoporders.New(log),
expiringStopOrders: common.NewExpiringOrders(),
banking: banking,
allowedSellers: allowedSellers,
}
liquidity.SetGetStaticPricesFunc(market.getBestStaticPricesDecimal)

Expand Down Expand Up @@ -310,6 +318,11 @@ func (m *Market) Update(ctx context.Context, config *types.Market) error {
m.liquidity.UpdateMarketConfig(riskModel, m.pMonitor)
m.updateLiquidityFee(ctx)

clear(m.allowedSellers)
for _, v := range config.AllowedSellers {
m.allowedSellers[v] = struct{}{}
}

if tickSizeChanged {
tickSizeInAsset, _ := num.UintFromDecimal(m.mkt.TickSize.ToDecimal().Mul(m.priceFactor))
peggedOrders := m.matching.GetActivePeggedOrderIDs()
Expand Down Expand Up @@ -1259,6 +1272,16 @@ func (m *Market) SubmitStopOrdersWithIDGeneratorAndOrderIDs(
return nil, common.ErrTradingNotAllowed
}

if fallsBelow != nil && fallsBelow.OrderSubmission != nil && !m.canSubmitMaybeSell(fallsBelow.Party, fallsBelow.OrderSubmission.Side) {
rejectStopOrders(types.StopOrderRejectionSellOrderNotAllowed, fallsBelow, risesAbove)
return nil, common.ErrSellOrderNotAllowed
}

if risesAbove != nil && risesAbove.OrderSubmission != nil && !m.canSubmitMaybeSell(risesAbove.Party, risesAbove.OrderSubmission.Side) {
rejectStopOrders(types.StopOrderRejectionSellOrderNotAllowed, risesAbove, risesAbove)
return nil, common.ErrSellOrderNotAllowed
}

now := m.timeService.GetTimeNow()
orderCnt := 0
if fallsBelow != nil {
Expand Down Expand Up @@ -1468,6 +1491,13 @@ func (m *Market) SubmitOrderWithIDGeneratorAndOrderID(ctx context.Context, order
return nil, common.ErrTradingNotAllowed
}

if !m.canSubmitMaybeSell(order.Party, order.Side) {
order.Status = types.OrderStatusRejected
order.Reason = types.OrderErrorSellOrderNotAllowed
m.broker.Send(events.NewOrderEvent(ctx, order))
return nil, common.ErrSellOrderNotAllowed
}

conf, _, err := m.submitOrder(ctx, order)
if err != nil {
return nil, err
Expand Down Expand Up @@ -2876,6 +2906,19 @@ func (m *Market) canTrade() bool {
m.mkt.State == types.MarketStateSuspendedViaGovernance
}

func (m *Market) canSubmitMaybeSell(party string, side types.Side) bool {
// buy side
// or network party
// or no empty allowedSellers list
// are always fine
if len(m.allowedSellers) <= 0 || side == types.SideBuy || party == types.NetworkParty {
return true
}

_, isAllowed := m.allowedSellers[party]
return isAllowed
}

// cleanupOnReject removes all resources created while the market was on PREPARED state.
// at this point no fees would have been collected or anything like this.
func (m *Market) cleanupOnReject(ctx context.Context) {
Expand Down
5 changes: 5 additions & 0 deletions core/execution/spot/market_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ func NewMarketFromSnapshot(
}

now := timeService.GetTimeNow()
allowedSellers := map[string]struct{}{}
for _, v := range mkt.AllowedSellers {
allowedSellers[v] = struct{}{}
}
market := &Market{
log: log,
mkt: mkt,
Expand Down Expand Up @@ -190,6 +194,7 @@ func NewMarketFromSnapshot(
hasTraded: em.HasTraded,
orderHoldingTracker: NewHoldingAccountTracker(mkt.ID, log, collateralEngine),
banking: banking,
allowedSellers: allowedSellers,
}
liquidity.SetGetStaticPricesFunc(market.getBestStaticPricesDecimal)
for _, p := range em.Parties {
Expand Down
2 changes: 2 additions & 0 deletions core/governance/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@ func (e *Engine) updatedSpotMarketFromProposal(p *proposal) (*types.Market, type
TickSize: terms.Changes.TickSize,
LiquidityFeeSettings: terms.Changes.LiquidityFeeSettings,
EnableTxReordering: terms.Changes.EnableTxReordering,
AllowedSellers: append([]string{}, terms.Changes.AllowedSellers...),
},
}

Expand Down Expand Up @@ -1339,6 +1340,7 @@ func (e *Engine) updatedMarketFromProposal(p *proposal) (*types.Market, types.Pr
TickSize: terms.Changes.TickSize,
EnableTxReordering: terms.Changes.EnableTxReordering,
AllowedEmptyAmmLevels: &allowedEmptyAMMLevels,
AllowedSellers: append([]string{}, terms.Changes.AllowedSellers...),
},
}

Expand Down
2 changes: 2 additions & 0 deletions core/governance/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ func buildMarketFromProposal(
TickSize: definition.Changes.TickSize,
EnableTxReordering: definition.Changes.EnableTxReordering,
AllowedEmptyAmmLevels: allowedEmptyAMMLevels,
AllowedSellers: append([]string{}, definition.Changes.AllowedSellers...),
}
if fCap := market.TradableInstrument.Instrument.Product.Cap(); fCap != nil {
marginCalc.FullyCollateralised = fCap.FullyCollateralised
Expand Down Expand Up @@ -388,6 +389,7 @@ func buildSpotMarketFromProposal(
MarkPriceConfiguration: defaultMarkPriceConfig,
TickSize: definition.Changes.TickSize,
EnableTxReordering: definition.Changes.EnableTxReordering,
AllowedSellers: append([]string{}, definition.Changes.AllowedSellers...),
}
if err := assignSpotRiskModel(definition.Changes, market.TradableInstrument); err != nil {
return nil, types.ProposalErrorUnspecified, err
Expand Down
9 changes: 9 additions & 0 deletions core/types/governance_new_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,17 @@ type NewMarketConfiguration struct {
TickSize *num.Uint
EnableTxReordering bool
AllowedEmptyAmmLevels *uint64
AllowedSellers []string
}

func (n NewMarketConfiguration) IntoProto() *vegapb.NewMarketConfiguration {
riskParams := n.RiskParameters.newRiskParamsIntoProto()
md := make([]string, 0, len(n.Metadata))
md = append(md, n.Metadata...)

allowedSellers := make([]string, 0, len(n.AllowedSellers))
allowedSellers = append(allowedSellers, n.AllowedSellers...)

var instrument *vegapb.InstrumentConfiguration
if n.Instrument != nil {
instrument = n.Instrument.IntoProto()
Expand Down Expand Up @@ -463,6 +467,7 @@ func (n NewMarketConfiguration) IntoProto() *vegapb.NewMarketConfiguration {
TickSize: n.TickSize.String(),
EnableTransactionReordering: n.EnableTxReordering,
AllowedEmptyAmmLevels: n.AllowedEmptyAmmLevels,
AllowedSellers: allowedSellers,
}
if n.Successor != nil {
r.Successor = n.Successor.IntoProto()
Expand Down Expand Up @@ -491,6 +496,7 @@ func (n NewMarketConfiguration) DeepClone() *NewMarketConfiguration {
if n.Instrument != nil {
cpy.Instrument = n.Instrument.DeepClone()
}
cpy.AllowedSellers = append(cpy.AllowedSellers, n.AllowedSellers...)
if n.PriceMonitoringParameters != nil {
cpy.PriceMonitoringParameters = n.PriceMonitoringParameters.DeepClone()
}
Expand Down Expand Up @@ -566,6 +572,9 @@ func NewMarketConfigurationFromProto(p *vegapb.NewMarketConfiguration) (*NewMark
md := make([]string, 0, len(p.Metadata))
md = append(md, p.Metadata...)

allowedSellers := make([]string, 0, len(p.AllowedSellers))
allowedSellers = append(allowedSellers, p.AllowedSellers...)

Check failure on line 576 in core/types/governance_new_market.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to allowedSellers (ineffassign)

var err error
var instrument *InstrumentConfiguration
if p.Instrument != nil {
Expand Down
3 changes: 2 additions & 1 deletion core/types/governance_new_market_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ func TestNewMarketProposalMapping(t *testing.T) {
MaxFractionConsumed: "0.01",
DisposalSlippageRange: "0.1",
},
TickSize: "1",
TickSize: "1",
AllowedSellers: []string{},
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions core/types/governance_new_spot_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ type NewSpotMarketConfiguration struct {
LiquidityFeeSettings *LiquidityFeeSettings
TickSize *num.Uint
EnableTxReordering bool
AllowedSellers []string

// New market risk model parameters
//
Expand Down Expand Up @@ -165,6 +166,7 @@ func (n NewSpotMarketConfiguration) IntoProto() *vegapb.NewSpotMarketConfigurati
LiquidityFeeSettings: n.LiquidityFeeSettings.IntoProto(),
TickSize: n.TickSize.String(),
EnableTransactionReordering: n.EnableTxReordering,
AllowedSellers: append([]string{}, n.AllowedSellers...),
}
switch rp := riskParams.(type) {
case *vegapb.NewSpotMarketConfiguration_Simple:
Expand All @@ -183,6 +185,7 @@ func (n NewSpotMarketConfiguration) DeepClone() *NewSpotMarketConfiguration {
SLAParams: n.SLAParams.DeepClone(),
TickSize: n.TickSize.Clone(),
EnableTxReordering: n.EnableTxReordering,
AllowedSellers: append([]string{}, n.AllowedSellers...),
}
cpy.Metadata = append(cpy.Metadata, n.Metadata...)
if n.Instrument != nil {
Expand Down Expand Up @@ -261,6 +264,7 @@ func NewSpotMarketConfigurationFromProto(p *vegapb.NewSpotMarketConfiguration) (
LiquidityFeeSettings: liquidityFeeSettings,
TickSize: tickSize,
EnableTxReordering: p.EnableTransactionReordering,
AllowedSellers: append([]string{}, p.AllowedSellers...),
}
if p.RiskParameters != nil {
switch rp := p.RiskParameters.(type) {
Expand Down
4 changes: 4 additions & 0 deletions core/types/governance_update_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ type UpdateMarketConfiguration struct {
TickSize *num.Uint
EnableTxReordering bool
AllowedEmptyAmmLevels *uint64
AllowedSellers []string
}

func (n UpdateMarketConfiguration) String() string {
Expand All @@ -166,6 +167,7 @@ func (n UpdateMarketConfiguration) DeepClone() *UpdateMarketConfiguration {
TickSize: n.TickSize.Clone(),
EnableTxReordering: n.EnableTxReordering,
AllowedEmptyAmmLevels: n.AllowedEmptyAmmLevels,
AllowedSellers: append([]string{}, n.AllowedSellers...),
}
cpy.Metadata = append(cpy.Metadata, n.Metadata...)
if n.Instrument != nil {
Expand Down Expand Up @@ -239,6 +241,7 @@ func (n UpdateMarketConfiguration) IntoProto() *vegapb.UpdateMarketConfiguration
TickSize: n.TickSize.String(),
EnableTransactionReordering: n.EnableTxReordering,
AllowedEmptyAmmLevels: n.AllowedEmptyAmmLevels,
AllowedSellers: append([]string{}, n.AllowedSellers...),
}
switch rp := riskParams.(type) {
case *vegapb.UpdateMarketConfiguration_Simple:
Expand Down Expand Up @@ -341,6 +344,7 @@ func UpdateMarketConfigurationFromProto(p *vegapb.UpdateMarketConfiguration) (*U
TickSize: tickSize,
EnableTxReordering: p.EnableTransactionReordering,
AllowedEmptyAmmLevels: p.AllowedEmptyAmmLevels,
AllowedSellers: append([]string{}, p.AllowedSellers...),
}
if p.RiskParameters != nil {
switch rp := p.RiskParameters.(type) {
Expand Down
Loading

0 comments on commit 775d16a

Please sign in to comment.