From ca365242ed7a94e3f1e0bf21d3d370a941e5bc47 Mon Sep 17 00:00:00 2001 From: Charlie <99198652+cdummett@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:51:48 +0100 Subject: [PATCH] chore: update genbutemple branch with colosseo II (#2322) * feat: add AC for vAMM during opening auction * chore: typo * fix: reword * feat: Updates to fix up equations (#2303) * feat: tx trade ordering (#2231) * feat: Order trade transactions within a block * feat: AMM Estimates (#2282) * feat: Estimate within range * refactor: first stab at max block auction * refactor: add defaults * refactor: formalise action interaction + ACs * refactor: remove supplied liquidity requirement from ACs * chore: update approbation * chore: fix CI issues * milestone rejig * fix fee mechanic milestone, reorder features * chore: remove impossible AC, but mention the behaviour in spec Signed-off-by: Elias Van Ootegem * chore: remove old AC from json Signed-off-by: Elias Van Ootegem * feat: separate fee discount components (#2293) * feat: Adding separate discount factor components * feat: Adding separate discount factor components * feat: Add ACs * feat: Fix AC code * feat: Fix AC code * feat: Review comments * feat: Adding high volume maker rebate * feat: Fix up eqs * feat: Remove duplicative naming * chore: Fix up markdown * refactor: add default value --------- Co-authored-by: Witold * rename 3 and rejig milestones * sorting * feat: change to average notional position * feat: calculate fraction of cumulative volume across window rather than average of fractions across window * fix: update spellcheck * Order spam (#2188) * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: wording Co-authored-by: Charlie <99198652+cdummett@users.noreply.github.com> * fix: spot correction Co-authored-by: Charlie <99198652+cdummett@users.noreply.github.com> * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * fix: clarify order spam * chore: clairfy spam protection for spot markets * fix: remove * fix: don't allow non-persistent orders that don't meet margin / value criteria * feat: Update spam tests on amendments * feat: Update spam tests on amendments * chore: revert inconsistent formatting * chore: fix markdownlint --------- Co-authored-by: Charlie <99198652+cdummett@users.noreply.github.com> Co-authored-by: Charlie Co-authored-by: Tom McLean * Revert "feat: average notional position" (#2320) * chore: bump LP 3.0 spec number --------- Signed-off-by: Elias Van Ootegem Co-authored-by: Jiajia-Cui Co-authored-by: David Siska <62546419+davidsiska-vega@users.noreply.github.com> Co-authored-by: Jiajia-Cui <92106936+Jiajia-Cui@users.noreply.github.com> Co-authored-by: Tom Co-authored-by: Witold Co-authored-by: Witold Co-authored-by: Edd Co-authored-by: Elias Van Ootegem Co-authored-by: Jeremy Letang --- protocol/0004-AMND-amends.md | 1 + protocol/0016-PFUT-product_builtin_future.md | 3 +- protocol/0026-AUCT-auctions.md | 8 +- protocol/0029-FEES-fees.md | 61 ++- protocol/0062-SPAM-spam_protection.md | 73 ++++ .../0083-RFPR-on_chain_referral_program.md | 96 ++++- protocol/0084-VDPR-volume_discount_program.md | 54 ++- protocol/0094-PRAC-protective_auctions.md | 17 +- .../0095-HVMR-high_volume_maker_rebate.md | 70 ++++ ...s.md => 0096-LIQM-liquidity_mechanisms.md} | 0 protocol/colosseo-features.json | 392 +++++++++++------- protocol/cosmic-features.json | 32 +- wordlist.txt | 1 + 13 files changed, 587 insertions(+), 221 deletions(-) create mode 100644 protocol/0095-HVMR-high_volume_maker_rebate.md rename protocol/{0095-LIQM-liquidity_mechanisms.md => 0096-LIQM-liquidity_mechanisms.md} (100%) diff --git a/protocol/0004-AMND-amends.md b/protocol/0004-AMND-amends.md index 4e618571b..fb8434cc9 100644 --- a/protocol/0004-AMND-amends.md +++ b/protocol/0004-AMND-amends.md @@ -27,6 +27,7 @@ - Attempting to alter details on a cancelled order will cause the amend to be rejected (0004-AMND-018). For product spot: (0004-AMND-046) - Attempting to alter details on an expired order will cause the amend to be rejected (0004-AMND-019). For product spot: (0004-AMND-047) - Amending expiry time of an active GTT order to a past time whilst also simultaneously amending the price of the order will cause the order to immediately expire with the order details updated to reflect the order details requiring amendment (0004-AMND-029). For product spot: (0004-AMND-048) +- An amendment which would result in the margin requirement for the order being smaller than `spam.order.minimalMarginQuantumMultiple` should fail with the order remaining unchanged (0004-AMND-061) For a party with no position on a given market: diff --git a/protocol/0016-PFUT-product_builtin_future.md b/protocol/0016-PFUT-product_builtin_future.md index b3dbe1246..e1b4444ac 100644 --- a/protocol/0016-PFUT-product_builtin_future.md +++ b/protocol/0016-PFUT-product_builtin_future.md @@ -92,6 +92,8 @@ Validation: - `fully-collateralised mode` is only allowed when there is a `max_price` specified - `binary_settlement` is only allowed when there is a `max_price` specified +Note that these fields are not specified on the market update types. Once a capped future is created and set to fully collateralised (and/or binary settlement), it cannot be changed. + ## Acceptance Criteria 1. Create a Cash Settled Future with trading termination triggered by a date/time based data source (0016-PFUT-001) @@ -125,4 +127,3 @@ Optional parameters: 1. Futures market can be created with a with [hardcoded risk factors](./0018-RSKM-quant_risk_models.ipynb). (0016-PFUT-026) 1. Updating a risk model on a futures market with regular risk model to with [hardcoded risk factors](./0018-RSKM-quant_risk_models.ipynb) results in recalculation of all margin levels in line with hardcoded values and collateral search/release where appropriate. (0016-PFUT-027) 1. Updating a risk model on a futures market with [hardcoded risk factors](./0018-RSKM-quant_risk_models.ipynb) to a regular risk model results in recalculation of all margin levels in line with the specified risk model (hardcoded value are no longer used) and collateral search/release where appropriate. (0016-PFUT-028) -1. It's not possible to modify the `fully-collateralised` flag with a market update transaction. (0016-PFUT-029) diff --git a/protocol/0026-AUCT-auctions.md b/protocol/0026-AUCT-auctions.md index 0ee427c6c..b4a9c7504 100644 --- a/protocol/0026-AUCT-auctions.md +++ b/protocol/0026-AUCT-auctions.md @@ -170,14 +170,14 @@ message Market { - Why it is in that period (e.g. Auction at open, liquidity sourcing, price monitoring) - When the auction will next attempt to uncross or if the auction period ended and the auction cannot be resolved for whatever reason then this should come blank or otherwise indicating that the system doesn't know when the auction ought to end. - A market with default trading mode "continuous trading" will start with an opening auction. The opening auction will run from the close of voting on the market proposal (assumed to pass successfully) until: - 1. the enactment time assuming there are orders crossing on the book and [liquidity is supplied](./0044-LIME-lp_mechanics.md#commit-liquidity-network-transaction). (0026-AUCT-017). For product spot, the enactment time assuming there are orders crossing on the book, there is no need for the supplied liquidity to exceed a threshold to exit an auction: (0026-AUCT-029) + 1. the enactment time assuming there are orders crossing on the book, there is no need for the supplied liquidity to exceed a threshold to exit an auction. (0026-AUCT-038). For product spot, the enactment time assuming there are orders crossing on the book, there is no need for the supplied liquidity to exceed a threshold to exit an auction: (0026-AUCT-029) 2. past the enactment time if there is no [liquidity supplied](./0044-LIME-lp_mechanics.md#commit-liquidity-network-transaction). The auction won't end until sufficient liquidity is committed. (0026-AUCT-018) 3. past the enactment time if [liquidity is supplied](./0044-LIME-lp_mechanics.md#commit-liquidity-network-transaction) but the uncrossing volume will create open interest that is larger than what the [supplied stake can support](./0041-TSTK-target_stake.md). It will only end if - more liquidity is committed (0026-AUCT-019) - or if orders are cancelled such that the uncrossing volume will create open interest sufficiently small so that the original stake can support it. (0026-AUCT-020) - 4. past the enactment time if there are orders crossing on the book and [liquidity is supplied](./0044-LIME-lp_mechanics.md#commit-liquidity-network-transaction) but after the auction uncrossing we will not have - - best bid; it will still open. (0026-AUCT-021) - - or best ask; it will still open. (0026-AUCT-022) + 4. past the enactment time if there are orders crossing on the book (there is no need for the supplied liquidity to exceed a threshold to exit an auction) but after the auction uncrossing we will not have + - best bid; it will still open. (0026-AUCT-039) + - or best ask; it will still open. (0026-AUCT-040) - When entering an auction, all GFN orders will be cancelled. (0026-AUCT-015). For product spot: (0026-AUCT-031) - When leaving an auction, all GFA orders will be cancelled. (0026-AUCT-016). For product spot: (0026-AUCT-032) diff --git a/protocol/0029-FEES-fees.md b/protocol/0029-FEES-fees.md index 6573baea3..31f40d451 100644 --- a/protocol/0029-FEES-fees.md +++ b/protocol/0029-FEES-fees.md @@ -9,7 +9,7 @@ An order may cross with more than one other order, creating multiple trades. Eac The trading fee is: -`total_fee = infrastructure_fee + maker_fee + liquidity_fee` +`total_fee = infrastructure_fee + maker_fee + liquidity_fee + buyback_fee + treasury_fee` `infrastructure_fee = fee_factor[infrastructure] * trade_value_for_fee_purposes` @@ -17,6 +17,10 @@ The trading fee is: `liquidity_fee = fee_factor[liquidity] * trade_value_for_fee_purposes` +`buyback_fee = fee_factor[buyback] * trade_value_for_fee_purposes` + +`treasury_fee = fee_factor[treasury] * trade_value_for_fee_purposes` + Fees are calculated and collected in the settlement currency of the market, collected from the general account. Fees are collected first from the trader's account and then margin from account balance. If the general account doesn't have sufficient balance, then the remaining fee amount is collected from the margin account. If this is still insufficient then different rules apply between continuous trading and auctions (details below). Note that maker_fee = 0 if there is no maker, taker relationship between the trading parties (in particular auctions). @@ -25,14 +29,14 @@ Note that maker_fee = 0 if there is no maker, taker relationship between the tra Before fees are transferred, if there is an [active referral program](./0083-RFPR-on_chain_referral_program.md) or [volume discount program](./0085-VDPR-volume_discount_program.md), each parties fee components must be modified as follows. -Note, discounts are calculated and applied one after the other and **before** rewards are calculated. +Note, discounts are calculated and applied one after the other and **before** rewards are calculated. Additionally, no benefit discounts can be applied to the treasury or buyback fee components as these may be required for the `high volume market maker rebate`. 1. Calculate any referral discounts due to the party. ```pseudo - infrastructure_fee_referral_discount = floor(original_infrastructure_fee * referral_discount_factor) - liquidity_fee_referral_discount = floor(original_liquidity_fee * referral_discount_factor) - maker_fee_referral_discount = floor(original_maker_fee * referral_discount_factor) + infrastructure_fee_referral_discount = floor(original_infrastructure_fee * referral_infrastructure_discount_factor) + liquidity_fee_referral_discount = floor(original_liquidity_fee * referral_liquidity_discount_factor) + maker_fee_referral_discount = floor(original_maker_fee * referral_maker_discount_factor) ``` 1. Apply referral discounts to the original fee. @@ -46,9 +50,9 @@ Note, discounts are calculated and applied one after the other and **before** re 1. Calculate any volume discounts due to the party. ```pseudo - infrastructure_fee_volume_discount = floor(infrastructure_fee_after_referral_discount * volume_discount_factor) - liquidity_fee_volume_discount = floor(liquidity_fee_after_referral_discount * volume_discount_factor) - maker_fee_volume_discount = floor(maker_fee_after_referral_discount * volume_discount_factor) + infrastructure_fee_volume_discount = floor(infrastructure_fee_after_referral_discount * volume_infrastructure_discount_factor) + liquidity_fee_volume_discount = floor(liquidity_fee_after_referral_discount * volume_liquidity_discount_factor) + maker_fee_volume_discount = floor(maker_fee_after_referral_discount * volume_maker_discount_factor) ``` 1. Apply any volume discounts to the fee after referral discounts. @@ -62,9 +66,9 @@ Note, discounts are calculated and applied one after the other and **before** re 1. Calculate any referral rewards due to the parties referrer (Note we are using the updated fee components from step 4 and the `referralProgram.maxReferralRewardProportion` is the network parameter described in the [referral program spec](./0083-RFPR-on_chain_referral_program.md#network-parameters)) ```pseudo - infrastructure_fee_referral_reward = floor(infrastructure_fee_after_volume_discount * min(referral_reward_factor * referral_reward_multiplier, referralProgram.maxReferralRewardProportion)) - liquidity_fee_referral_reward = floor(liquidity_fee * min(liquidity_fee_after_volume_discount * min(referral_reward_factor * referral_reward_multiplier, referralProgram.maxReferralRewardProportion)) - maker_fee_referral_reward = floor(maker_fee * min(maker_fee_after_volume_discount * min(referral_reward_factor * referral_reward_multiplier, referralProgram.maxReferralRewardProportion)) + infrastructure_fee_referral_reward = floor(infrastructure_fee_after_volume_discount * min(referral_infrastructure_reward_factor * referral_reward_multiplier, referralProgram.maxReferralRewardProportion)) + liquidity_fee_referral_reward = floor(liquidity_fee * min(liquidity_fee_after_volume_discount * min(referral_liquidity_reward_factor * referral_reward_multiplier, referralProgram.maxReferralRewardProportion))) + maker_fee_referral_reward = floor(maker_fee * min(maker_fee_after_volume_discount * min(referral_maker_reward_factor * referral_reward_multiplier, referralProgram.maxReferralRewardProportion))) ``` 1. Finally, update the fee components by applying the rewards. @@ -82,10 +86,14 @@ Note, discounts are calculated and applied one after the other and **before** re - infrastructure: staking/governance system/engine (network wide) - maker: market framework / market making (network wide) - liquidity: market making system (per market) +- treasury: Fees sent to network treasury for later usage via governance votes (network wide) +- buyback: Fees used to purchase governance tokens to the protocol via regular auctions (network wide) The infrastructure fee factor is set by a network parameter `market.fee.factors.infrastructureFee` and a reasonable default value is `fee_factor[infrastructure] = 0.0005 = 0.05%`. The maker fee factor is set by a network parameter `market.fee.factors.makerFee` and a reasonable default value is `fee_factor[maker] = 0.00025 = 0.025%`. The liquidity fee factor is set by an auction-like mechanism based on the liquidity provisions committed to the market, see [setting LP fees](./0042-LIQF-setting_fees_and_rewarding_lps.md). +The treasury fee factor is set by the network parameter `market.fee.factors.treasuryFee` with a default value should of `0`. +The buyback fee factor is set by the network parameter `market.fee.factors.buybackFee` with a default value should of `0`. trade_value_for_fee_purposes: @@ -107,15 +115,26 @@ If the transfer fails: 1. If we are in continuous trading mode, than trades should be discarded, any orders on the book that would have been hit should remain in place with previous remaining size intact and the incoming order should be rejected (not enough fees error). This functionality requires to match orders and create trades without changing the state of the order book or passing trades downstream so that the execution of the transaction can be discarded with no impact on the order book if needed. Other than the criteria whether to proceed or discard, this is exactly the same functionality required to implement [price monitoring](./0032-PRIM-price_monitoring.md). -2. If we are in auction mode, ignore the shortfall (and see more details below). +1. If we are in auction mode, ignore the shortfall (and see more details below). + +The transfer of fees must be completed before performing the normal post-trade calculations (MTM Settlement, position resolution etc...). The transfers have to be identifiable as fee transfers and separate for the different components. -The transfer of fees must be completed before performing the normal post-trade calculations (MTM Settlement, position resolution etc...). The transfers have to be identifiable as fee transfers and separate for the three components. +Additionally, a `high_volume_market_maker_rebate` may be necessary which will be taken from the `treasury/buyback_fee` components. This will be calculated as: + +1. Determine whether the maker party of the trade (if there is one) qualifies for a `high volume market maker rebate` and, if so, at what rate. +1. Calculate the fee that this corresponds to as `high_volume_maker_fee = high_volume_factor * trade_value_for_fee_purposes`. +1. Take this fee from the `treasury_fee` and `buyback_fee` (protocol restrictions on governance changes ensure that `treasury_fee + buyback_fee >= high_volume_maker_fee` is always true) as a proportion of their relative sizes, i.e.: + 1. `high_volume_maker_fee = high_volume_factor * trade_value_for_fee_purposes` + 1. `treasury_fee = treasury_fee * (1 - high_volume_maker_fee / (treasury_fee + buyback_fee))` + 1. `buyback_fee = buyback_fee * (1 - high_volume_maker_fee / (treasury_fee + buyback_fee))` Now [apply benefit factors](#applying-benefit-factors) and then distribute funds from the "temporary fee bucket" as follows: 1. The `infrastructure_fee` is transferred to infrastructure fee pool for that asset. Its distribution is described in [0061 - Proof of Stake rewards](./0061-REWP-pos_rewards.md). In particular, at the end of each epoch the amount due to each validator and delegator is to be calculated and then distributed subject to validator score and type. -1. The `maker_fee` is transferred to the relevant party (the maker). +1. The `maker_fee` and any `high_volume_maker_fee` are transferred to the relevant party (the maker). 1. The `liquidity_fee` is distributed as described in [this spec](./0042-LIQF-setting_fees_and_rewarding_lps.md). +1. The `treasury_fee` is transferred to the treasury fee pool for that asset, where it will remain until community governance votes for transfers. +1. The `buyback_fee` is transferred to the buyback fee pool for that asset, where it will remain until community governance votes for transfers or a regular purchase program is set up. 1. The referral fee components (if any) can then be individually transferred to the relevant party (the referee). ### During Continuous Trading @@ -126,9 +145,9 @@ The "aggressor or price taker" pays the fee. The "passive or price maker" party ### Normal Auctions (including market protection and opening auctions) -During normal auctions there is no "price maker" both parties are "takers". Each side in a matched trade should contribute 1/2 of the infrastructure_fee + liquidity_fee. Note that this does not include a maker fee. +During normal auctions there is no "price maker" both parties are "takers". Each side in a matched trade should contribute 1/2 of the infrastructure_fee + liquidity_fee + treasury_fee + buyback_fee. Note that this does not include a maker fee. -Fees calculated and collected from general + margin as in continuous trading *but* if a party has insufficient capital to cover the trading fee then in auction the trade *still* *goes* *ahead* as long as the margin account should have enough left after paying the fees to cover maintenance level of margin for the orders and then converted trades. The fee is distributed so that the infrastructure_fee is paid first and only then the liquidity_fee. +Fees calculated and collected from general + margin as in continuous trading *but* if a party has insufficient capital to cover the trading fee then in auction the trade *still* *goes* *ahead* as long as the margin account should have enough left after paying the fees to cover maintenance level of margin for the orders and then converted trades. The fee is distributed so that the infrastructure_fee is paid first and only then the liquidity_fee/treasury_fee/buyback_fee. During an opening auction of a market, no fees are collected. @@ -168,7 +187,11 @@ For example, Ether is 18 decimals (wei). The smallest unit, non divisible is 1 w ### Applying benefit factors 1. Referee discounts are correctly calculated and applied for each taker fee component during continuous trading (assuming no volume discounts due to party) (0029-FEES-023) - - `infrastructure_referral_fee_discount` + - `infrastructure_fee_referral_discount` + - `liquidity_fee_referral_discount` + - `maker_fee_referral_discount` +1. Referee discounts with differing discounts across the three factors are correctly calculated and applied for each taker fee component during continuous trading (assuming no volume discounts due to party) (0029-FEES-034) + - `infrastructure_fee_referral_discount` - `liquidity_fee_referral_discount` - `maker_fee_referral_discount` 1. Referee discounts are correctly calculated and applied for each fee component when exiting an auction (assuming no volume discounts due to party) (0029-FEES-024) @@ -178,6 +201,10 @@ For example, Ether is 18 decimals (wei). The smallest unit, non divisible is 1 w - `infrastructure_fee_referral_reward` - `liquidity_fee_referral_reward` - `maker_fee_referral_reward` +1. Referrer rewards with differing reward factors are correctly calculated and transferred for each fee component during continuous trading (assuming no volume discounts due to party) (0029-FEES-035) + - `infrastructure_fee_referral_reward` + - `liquidity_fee_referral_reward` + - `maker_fee_referral_reward` 1. Referrer rewards are correctly calculated and transferred for each fee component when exiting an auction (assuming no volume discounts due to party) (0029-FEES-026) - `infrastructure_fee_referral_reward` - `liquidity_fee_referral_reward` diff --git a/protocol/0062-SPAM-spam_protection.md b/protocol/0062-SPAM-spam_protection.md index 87cc36501..d71f80ce8 100644 --- a/protocol/0062-SPAM-spam_protection.md +++ b/protocol/0062-SPAM-spam_protection.md @@ -83,6 +83,41 @@ Further, each party is allowed to submit up to `n` transactions per epoch where **Note** `spam.protection.max.updatePartyProfile` must be an integer greater than or equal to `0` (and default to `5`). +### Transaction Spam + +#### Derivative markets + +Before any order or liquidity commitment is accepted for a perpetual futures or expiring futures check that the party has `margin + order margin + general > 0` with `margin` being the balance in the margin account for the relevant, `order margin` is the balance for the order margin if party is in isolated margin mode for the for the relevant market and `general` the balance in the general account for the relevant asset. Orders from parties that don't meet this criteria are rejected. This is to be done after the PoW check. + +Further, given the network parameter: `spam.order.minimalMarginQuantumMultiple` (between 0 and infinite) + +If the maintenance margin for a given transaction is smaller than the parameter `spam.order.minimalMarginQuantumMultiple`, then the transaction is pre-block rejected. +I.e. if `(rf + linear slippage param) x size x price < spam.order.minimalMarginQuantumMultiple x asset quantum amount` then the order is rejected. Here `rf` is the risk factor (and will be different for long and for short) `linear slippage param` is a market parameter and `size` and `price` are assumed to be correctly scaled by, PDPs and MDPs respectively. + +For pegged orders `mark price +/- offset` should be used in place of price. The `mark price` value can be cached from end of last block (if that helps for performance, we need this to be cheap). In opening auctions pegged orders should be rejected. + +For stop / position linked orders: we don't necessarily have either price or size. However there is a limit on the number per key so we let these through. + +Finally, if the market does not exist and thus the maintenance margin is not defined, the transaction is rejected. + +#### Spot markets + +Before any order or liquidity commitment is accepted for a spot market, check that the party has balances where `holding + general > 0` for the asset that the order is potentially disposing of / committing in terms of liquidity. Orders from parties that don't meet this criteria are rejected. This is to be done after the PoW check. + +Further, given the network parameter: `spam.order.minimalHoldingQuantumMultiple` (between 0 and infinite) + +If the holding requirement for a given transaction is smaller than the parameter `spam.order.minimalHoldingQuantumMultiple`, then the transaction is pre-block rejected. +I.e. if `size x price < spam.order.minimalHoldingQuantumMultiple x quote asset quantum amount` then the order is rejected. Here `size` and `price` are assumed to be correctly scaled by, PDPs and MDPs respectively. + +For pegged orders `last traded price +/- offset` should be used in place of price. The `last traded price` value can be cached from end of last block (if that helps for performance). In opening auctions pegged orders should be rejected. + +#### All markets + +The following points apply generally to both derivative and spot markets: + +- For amendments and cancellations: Check that the party has at least `spam.order.minimalMarginQuantumMultiple` margin within the margin account on the market of the order, implying they have active orders or positions on the market. If they do not then reject the transaction. +- For batch transactions: each order has to pass its own order spam check; if any order in the batch fails the check then reject the whole batch. +- Checks should be completed before the gas cost calculation as rejected transactions should not get into the calculation of the gas cost. ### Related topics @@ -128,4 +163,42 @@ More than 360 delegation changes in one epoch (or, respectively, the value of `s - A party who has submitted strictly more than `spam.protection.max.updatePartyProfile` `UpdatePartyProfile` transactions in an epoch should have any future `UpdatePartyProfile` transactions in that epoch **pre-block** rejected (0062-SPAM-038). - A party who has submitted more than `spam.protection.max.updatePartyProfile` `UpdatePartyProfile` transactions in the current epoch plus in the current block, should have their `UpdatePartyProfile` transactions submitted in the current block **pre-block** rejected (0062-SPAM-039). +- In a derivatives market, issue a set of orders starting with the minimum price, and doubling the order price with every order. Once the first order passes the spam filter, quadruple the parameter `spam.order.minimalMarginQuantumMultiple` and continue. Once the next order passes the filter, quadruple the quantum size for the underlying asset, and continue until an order passes the filter again. Verify that all rejected orders had a margin smaller than `spam.order.minimalMarginQuantumMultiple`, and all accepted ones one bigger or equal. (0062-SPAM-043). +- In a derivatives market, issue a set of orders for an existing, but not yet enacted market, starting with the minimum price, and doubling the order price with every order. Once the first order passes the spam filter, quadruple the parameter `spam.order.minimalMarginQuantumMultiple` and continue. Once the next order passes the filter, quadruple the quantum size for the underlying asset, and continue until an order passes the filter again. Verify that all rejected orders had a margin smaller than `spam.order.minimalMarginQuantumMultiple`, and all accepted ones one bigger or equal. (0062-SPAM-044). +- Create an order for a non-existing derivatives market, and verify that it is rejected by the spam filter. (0062-SPAM-045). +- In a derivatives market, pegged orders are rejected during an opening auction (0062-SPAM-047). +- In a derivatives market, Pegged orders are accepted once the market has a mark price and the mark price is used as the reference price for the spam check purposes and the order meets `spam.order.minimalMarginQuantumMultiple` requirement (0062-SPAM-048). +- In a derivatives market, pegged orders are rejected if the market has a mark price and the mark price is used as the reference price for the spam check purposes *but* the order fails `spam.order.minimalMarginQuantumMultiple` requirement (0062-SPAM-049). +- In a derivatives market, batch order is accepted if all orders in batch individually meet the `spam.order.minimalMarginQuantumMultiple` requirement (0062-SPAM-050). +- In a derivatives market, batch order is rejected if one or more orders in batch individually *fail to meet* the `spam.order.minimalMarginQuantumMultiple` requirement (0062-SPAM-062). +- In a derivatives market, order amends are accepted if the order with the new price / size meets the `spam.order.minimalMarginQuantumMultiple` requirement (0062-SPAM-051). +- In a derivatives market, order amends are rejected if the order with the new price / size meets *fails to meet* the `spam.order.minimalMarginQuantumMultiple` requirement (0062-SPAM-052). + +- In a spot market, issue a set of orders starting with the minimum price, and doubling the order price with every order. Once the first order passes the spam filter, quadruple the parameter `spam.order.minimalHoldingQuantumMultiple` and continue. Once the next order passes the filter, quadruple the quantum size for the underlying asset, and continue until an order passes the filter again. Verify that all rejected orders had a margin smaller than `spam.order.minimalHoldingQuantumMultiple`, and all accepted ones one bigger or equal. (0062-SPAM-064). +- In a spot market, pegged orders are rejected during an opening auction (0062-SPAM-066). +- In a spot market, pegged orders are accepted once the market has a last trade price and the last trade price is used as the reference price for the spam check purposes and the order meets `spam.order.minimalHoldingQuantumMultiple` requirement (0062-SPAM-067). +- In a spot market, pegged orders are rejected if the market has a last trade price and the last trade price is used as the reference price for the spam check purposes *but* the order fails `spam.order.minimalHoldingQuantumMultiple` requirement (0062-SPAM-068). +- In a spot market, batch order is accepted if all orders in batch individually meet the `spam.order.minimalHoldingQuantumMultiple` requirement (0062-SPAM-069). +- In a spot market, batch order is rejected if one or more orders in batch individually *fail to meet* the `spam.order.minimalHoldingQuantumMultiple` requirement (0062-SPAM-070). +- In a spot market, order amends are accepted if the order with the new price / size meets the `spam.order.minimalHoldingQuantumMultiple` requirement (0062-SPAM-071). +- In a spot market, order amends are rejected if the order with the new price / size meets *fails to meet* the `spam.order.minimalHoldingQuantumMultiple` requirement (0062-SPAM-072). + +#### Balance checks + +On perps and futures markets order are rejected `margin + order margin + general = 0` with `margin` being the margin account balance for the relevant market, `order margin` being the order margin account balance for the relevant market and general being the general account balance for the settlement asset for the market for + +- market orders in cross margin mode and in isolated margin mode (0062-SPAM-053). +- limit orders in cross margin mode and in isolated margin mode (0062-SPAM-054). +- pegged orders in cross margin mode and in isolated margin mode (0062-SPAM-055). +- liquidity commitment (0062-SPAM-056). +- stop-loss / position-linked order in cross margin mode and in isolated margin mode (0062-SPAM-057). + +On spot markets orders are rejected if `holding + general = 0` for the asset that the order is (or potentially is) disposing of with the following order types + +- market orders (0062-SPAM-063). +- limit orders (0062-SPAM-058). +- pegged orders (0062-SPAM-059). +- liquidity commitment (0062-SPAM-060). +- stop-loss / position-linked order (0062-SPAM-061). + > **Note**: If other governance functionality (beyond delegation-changes, votes, and proposals) are added, the spec and its acceptance criteria need to be augmented accordingly. This issue will be fixed in a follow up version. diff --git a/protocol/0083-RFPR-on_chain_referral_program.md b/protocol/0083-RFPR-on_chain_referral_program.md index 39846dbe4..74da638d7 100644 --- a/protocol/0083-RFPR-on_chain_referral_program.md +++ b/protocol/0083-RFPR-on_chain_referral_program.md @@ -46,8 +46,14 @@ Enabling or changing the terms of the on-chain referral program can be proposed - `benefit_tiers`: a list of dictionaries (with the below fields) defining the reward and discount factors from referrals - `minimum_running_notional_taker_volume`: the required [`referral_set_running_notional_taker_volume`](#referral-set-volumes) in quantum units for parties to access this tier - `minimum_epochs`: the required number of epochs a referee must have been in a referral set to access this tier - - `referral_reward_factor`: the proportion of the referee's taker fees to be rewarded to the referrer - - `referral_discount_factor`: the proportion of the referee's taker fees to be discounted + - `referral_reward_factors`: the proportions of the referee's taker fees to be rewarded to the referrer + - `referral_maker_reward_factor`: the factor to reward the referrer from the maker fee component of any fees paid + - `referral_infrastructure_reward_factor`: the factor to reward the referrer from the infrastructure fee component of any fees paid + - `referral_liquidity_reward_factor`: the factor to reward the referrer from the liquidity provider fee component of any fees paid + - `referral_discount_factors`: the proportions of the referee's taker fees to be discounted + - `referral_maker_discount_factor`: the factor to discount the maker fee component of any fees paid + - `referral_infrastructure_discount_factor`: the factor to discount the infrastructure fee component of any fees paid + - `referral_liquidity_discount_factor`: the factor to discount the liquidity provider fee component of any fees paid - `staking_tiers`: a list of dictionaries (with the below fields) defining the multipliers from staking - `minimum_staked_tokens`: the required number of governance tokens ($VEGA) a referrer must be staking to receive the multiplier - `referral_reward_multiplier`: the multiplier applied to the referral_reward_factor when calculating referral rewards due to the referrer. @@ -61,20 +67,44 @@ message UpdateReferralProgram{ { "minimum_running_notional_taker_volume": 10000, "minimum_epochs": 1, - "referral_reward_factor": 0.001, - "referral_discount_factor": 0.001, + "referral_reward_factors": { + "referral_maker_reward_factor": 0.001, + "referral_infrastructure_reward_factor": 0.001, + "referral_liquidity_reward_factor": 0.001 + }, + "referral_discount_factors": { + "referral_maker_discount_factor": 0.001, + "referral_infrastructure_discount_factor": 0.001, + "referral_liquidity_discount_factor": 0.001 + } }, { "minimum_running_notional_taker_volume": 20000, "minimum_epochs": 7, - "referral_reward_factor": 0.005, - "referral_discount_factor": 0.005, + "referral_reward_factors": { + "referral_maker_reward_factor": 0.005, + "referral_infrastructure_reward_factor": 0.005, + "referral_liquidity_reward_factor": 0.005 + }, + "referral_discount_factors": { + "referral_maker_discount_factor": 0.005, + "referral_infrastructure_discount_factor": 0.005, + "referral_liquidity_discount_factor": 0.005 + }, }, { "minimum_running_notional_taker_volume": 30000, "minimum_epochs": 31, - "referral_reward_factor": 0.010, - "referral_discount_factor": 0.010, + "referral_reward_factors": { + "referral_maker_reward_factor": 0.01, + "referral_infrastructure_reward_factor": 0.01, + "referral_liquidity_reward_factor": 0.01 + }, + "referral_discount_factors": { + "referral_maker_discount_factor": 0.01, + "referral_infrastructure_discount_factor": 0.01, + "referral_liquidity_discount_factor": 0.01 + }, }, ], staking_tiers: [ @@ -103,11 +133,11 @@ When submitting a referral program proposal through governance the following con - the number of tiers in `benefit_tiers` must be less than or equal to the network parameter `referralProgram.maxReferralTiers`. - all `minimum_running_notional_taker_volume` values must be an integer value strictly greater than `0`. - all `minimum_epochs` values must be an integer strictly greater than 0 -- all `referral_reward_factor` values must be greater than `0` and less than or equal to the network parameter `referralProgram.maxReferralRewardFactor`. +- all `referral_reward_factors` values must be greater than `0` and less than or equal to the network parameter `referralProgram.maxReferralRewardFactor`. - the number of tiers in `staking_tiers` must be less than or equal to the network parameter `referralProgram.maxReferralTiers`. - all `minimum_staked_tokens` values must be an integer value strictly greater than `0`. - all `referral_reward_multiplier` values must be a float value greater than or equal to `1`. -- all `referral_discount_factor` values must be greater than `0` and be less than or equal to the network parameter `referralProgram.maxReferralDiscountFactor`. +- all `referral_discount_factors` values must be greater than `0` and be less than or equal to the network parameter `referralProgram.maxReferralDiscountFactor`. - `window_length` must be an integer strictly greater than zero. The referral program will start the epoch after the `enactment_timestamp` is reached. @@ -286,28 +316,28 @@ The network can then calculate the set's `referral_set_running_notional_taker_vo ### Setting benefit factors and reward multipliers -Whilst a referral program is active, at the start of an epoch (after pending `ApplyReferralCode` transactions have been processed) the network must set the `referral_reward_factor` and `referral_discount_factor` for each referee. +Whilst a referral program is active, at the start of an epoch (after pending `ApplyReferralCode` transactions have been processed) the network must set the `referral_reward_factors` and `referral_discount_factors` for each referee. Note, when setting a referee's benefit factors we compare a sets `referral_set_running_notional_taker_volume` to a `minimum_running_notional_taker_volume` value. To prevent parties self-referring and moving teams, this `referral_set_running_notional_taker_volume` is always the value of the referee's original referral set. #### Setting the referral reward factor -The `referral_reward_factor` should be set by identifying the "highest" benefit tier where the following conditions are fulfilled. +The `referral_reward_factors` should be set by identifying the "highest" benefit tier where the following conditions are fulfilled. - `referral_set_running_notional_taker_volume` of the referee's **original** referral set is greater than or equal to the tier's `minimum_running_notional_taker_volume`. -The referee's `referral_reward_factor` is then set to the `referral_reward_factor` defined in the selected benefit tier. +The referee's `referral_reward_factors` are then set to the `referral_reward_factors` defined in the selected benefit tier. Note the **original** referrer is defined as the team of the referrer associated with the referee. See section [applying a referral code](#applying-a-referral-code) for more detail. #### Setting the referral discount factor -The `referral_discount_factor` should be set by identifying the "highest" benefit tier where **BOTH** the following conditions are fulfilled. +The `referral_discount_factors` should be set by identifying the "highest" benefit tier where **BOTH** the following conditions are fulfilled. - `referral_set_running_notional_taker_volume` of the referee's **original** referral set is greater than or equal to the tier's `minimum_running_notional_taker_volume`. - the referee has been a associated with the referral set for at least the tier's `minimum_epochs`. -The referee's `referral_discount_factor` is then set to the `referral_discount_factor` defined in the selected benefit tier. +The referee's `referral_discount_factors` are then set to the `referral_discount_factors` defined in the selected benefit tier. Note the **original** referrer is defined as the team of the referrer associated with the referee. See section [applying a referral code](#applying-a-referral-code) for more detail. @@ -329,20 +359,44 @@ Given: { "minimum_running_notional_taker_volume": 10000, "minimum_epochs": 0, - "referral_reward_factor": 0.001, - "referral_discount_factor": 0.001, + "referral_reward_factor": { + "maker_reward_factor": 0.001, + "infrastructure_reward_factor": 0.001, + "liquidity_reward_factor": 0.001 + }, + "referral_discount_factor": { + "maker_discount_factor": 0.001, + "infrastructure_discount_factor": 0.001, + "liquidity_discount_factor": 0.001 + }, }, { "minimum_running_notional_taker_volume": 20000, "minimum_epochs": 7, - "referral_reward_factor": 0.005, - "referral_discount_factor": 0.005, + "referral_reward_factor": { + "maker_reward_factor": 0.005, + "infrastructure_reward_factor": 0.005, + "liquidity_reward_factor": 0.005 + }, + "referral_discount_factor": { + "maker_discount_factor": 0.005, + "infrastructure_discount_factor": 0.005, + "liquidity_discount_factor": 0.005 + }, }, { "minimum_running_notional_taker_volume": 30000, "minimum_epochs": 31, - "referral_reward_factor": 0.010, - "referral_discount_factor": 0.010, + "referral_reward_factor": { + "maker_reward_factor": 0.01, + "infrastructure_reward_factor": 0.01, + "liquidity_reward_factor": 0. 01 + }, + "referral_discount_factor": { + "maker_discount_factor": 0.01, + "infrastructure_discount_factor": 0.01, + "liquidity_discount_factor": 0.01 + }, }, ] staking_tiers: [ diff --git a/protocol/0084-VDPR-volume_discount_program.md b/protocol/0084-VDPR-volume_discount_program.md index efbd1ef26..861e9811f 100644 --- a/protocol/0084-VDPR-volume_discount_program.md +++ b/protocol/0084-VDPR-volume_discount_program.md @@ -17,7 +17,10 @@ Enabling or changing the terms of the volume discount program can be proposed vi - `benefit_tiers`: a list of dictionaries with the following fields - `minimum_party_running_notional_taker_volume`: the required `party_running_notional_taker_volume` in quantum units for a party to access this tier - - `volume_discount_factor`: the proportion of the referees taker fees to be rewarded to the referrer + - `volume_discount_factors`: a dictionary with the following fields + - `maker_discount_factor`: the factor to discount the maker fee component of any fees paid + - `infrastructure_discount_factor`: the factor to discount the infrastructure fee component of any fees paid + - `lp_discount_factor`: the factor to discount the liquidity provider fee component of any fees paid - `end_of_program_timestamp`: the timestamp after which when the current epoch ends, the program will become inactive and benefits will be disabled. If this field is empty, the program runs indefinitely. - `window_length`: the number of epochs over which to evaluate a parties notional running volume @@ -27,15 +30,27 @@ message UpdateVolumeDiscountProgram{ benefit_tiers: [ { "minimum_party_running_notional_taker_volume": 1000, - "volume_discount_factor": 0.001, + "volume_discount_factors": { + "maker_discount_factor": 0.001, + "infrastructure_discount_factor": 0.001, + "lp_discount_factor": 0.001 + } }, { "minimum_party_running_notional_taker_volume": 20000, - "volume_discount_factor": 0.002, + "volume_discount_factors": { + "maker_discount_factor": 0.002, + "infrastructure_discount_factor": 0.002, + "lp_discount_factor": 0.002 + } }, { "minimum_party_running_notional_taker_volume": 30000, - "volume_discount_factor": 0.003, + "volume_discount_factors": { + "maker_discount_factor": 0.003, + "infrastructure_discount_factor": 0.003, + "lp_discount_factor": 0.003 + } }, ], end_of_program_timestamp: 123456789, @@ -49,7 +64,7 @@ When submitting a volume discount program proposal through governance the follow - a proposer cannot set an `end_of_program_timestamp` less than the proposals `enactment_time`. - the number of tiers in `benefit_tiers` must be less than or equal to the network parameter `volumeDiscountProgram.maxBenefitTiers`. - all `minimum_party_running_notional_taker_volume` values must be an integer value strictly greater than `0`. -- all `volume_discount_factor` values must be greater than or equal to `0` and less than or equal to the network parameter `volumeDiscountProgram.maxVolumeDiscountFactor`. +- all `volume_discount_factors` values must be greater than or equal to `0` and less than or equal to the network parameter `volumeDiscountProgram.maxVolumeDiscountFactor`. - `window_length` must be an integer strictly greater than zero. The volume discount program will start the epoch after the `enactment_timestamp` is reached. @@ -78,15 +93,27 @@ Given: benefit_tiers=[ { "minimum_party_running_notional_taker_volume": 10000, - "volume_discount_factor": 0.001, + "volume_discount_factors": { + "maker_discount_factor": 0.001, + "infrastructure_discount_factor": 0.001, + "lp_discount_factor": 0.001 + } }, { "minimum_party_running_notional_taker_volume": 20000, - "volume_discount_factor": 0.005, + "volume_discount_factors": { + "maker_discount_factor": 0.005, + "infrastructure_discount_factor": 0.005, + "lp_discount_factor": 0.005 + } }, { "minimum_party_running_notional_taker_volume": 30000, - "volume_discount_factor": 0.010, + "volume_discount_factors": { + "maker_discount_factor": 0.05, + "infrastructure_discount_factor": 0.05, + "lp_discount_factor": 0.05 + } }, ] @@ -94,7 +121,9 @@ And: party_running_notional_taker_volume=22353 Then: - volume_discount_factor=0.005 + maker_volume_discount_factor=0.005 + infrastructure_volume_discount_factor=0.005 + lp_volume_discount_factor=0.005 ``` This benefit factor is then fixed for the duration of the next epoch. @@ -109,7 +138,7 @@ The Parties API should expose the following information: - a list of all **parties** (by `id`) and the following metrics: - current `party_running_notional_taker_volume` (value at the start of the epoch) - - current `volume_discount_factor` applied to fees + - current `volume_discount_factors` applied to fees - the total amount discounted for the party The Trades API should now also expose the following additional information for every trade: @@ -127,7 +156,7 @@ The Trades API should now also expose the following additional information for e - the `end_of_program_timestamp` must be less than or equal to the proposals `enactment_time` (0084-VDPR-001). - the number of tiers in `benefit_tiers` must be less than or equal to the network parameter `volumeDiscountProgram.maxBenefitTiers` (0084-VDPR-002). - all `minimum_party_running_notional_taker_volume` values must be an integer strictly greater than 0 (0084-VDPR-017). - - all `volume_discount_factor` values must be greater than or equal to `0` and less than or equal to the network parameter `volumeDiscountProgram.maxVolumeDiscountFactor` (0084-VDPR-003). + - all `volume_discount_factors` values must be greater than or equal to `0` and less than or equal to the network parameter `volumeDiscountProgram.maxVolumeDiscountFactor` (0084-VDPR-003). - the `window_length` must be an integer strictly greater than zero (0084-VDPR-004). 1. A volume discount program should be started the first epoch change after the `enactment_datetime` is reached (0084-VDPR-005). 1. A volume discount program should be closed the first epoch change after the `end_of_program_timestamp` is reached (0084-VDPR-006). @@ -143,6 +172,7 @@ The Trades API should now also expose the following additional information for e ### Setting benefit factors -1. At the start of an epoch, each parties `volume_discount_factor` is reevaluated and fixed for the epoch (0084-VDPR-012). +1. At the start of an epoch, each parties `volume_discount_factors` are reevaluated and fixed for the epoch (0084-VDPR-012). 1. A parties `volume_discount_factor` is set equal to the factors in the highest benefit tier they qualify for (0084-VDPR-013). 1. If a party does not qualify for the lowest tier, their `volume_discount_factor`is set to `0` (0084-VDPR-014). +1. A `volume_discount_factors` tier with differing factors across the three options has each factor set correctly (0084-VDPR-018). diff --git a/protocol/0094-PRAC-protective_auctions.md b/protocol/0094-PRAC-protective_auctions.md index 95b7218c4..5231ec8f9 100644 --- a/protocol/0094-PRAC-protective_auctions.md +++ b/protocol/0094-PRAC-protective_auctions.md @@ -35,8 +35,15 @@ The default settings should be: | `1min` | `5min` | | `10min` | `1h` | | `1h` | `1h` | - | `6h` | `3h` | - | `24h` | `6h` | + | `6h` | `3h` | + | `24h` | `6h` | + + +## Interaction between different auction modes + +When market goes into auction mode from its default trading mode then the auction trigger which caused this should be listed as `trigger` on the API as long as that auction hasn't finished (including cases when it gets extended). + +When another trigger gets activated for the market then the end time of auction for that market should be the maximum of the original end time and that implied by the latest trigger. If the original end time is larger then nothing changes. If end time implied by the latest trigger is larger than the end time gets set to this value and the `extension_trigger` field gets set (or overwritten if market has already been in an extended auction at this point) to represent the latest trigger. Governance auction is assumed to have an infinite duration (it can only be ended with an appropriate governance auction and the timing of that action is generally unknown a priori). ## Acceptance criteria @@ -57,3 +64,9 @@ and at some point network determines that the length of the last block was 90s, - A market which has been in a per-market auction which was triggered before the network-wide auction was initiated remains in auction mode even if the exit condition for the original per-market auction gets satisfied before the network-wide auction ends. No intermediate trades get generated even in the presence of non-zero indicative volume at the point of that market's per-market auction exit condition being satisfied. The market only goes back into its default trading mode and possibly generates trades once the network-wide auction ends. (0094-PRAC-004) - A market which has been in a per-market auction which was triggered before the network-wide auction was initiated remains in auction mode once the network-wide auction ends if the exit condition for the original per-market auction hasn't been met at that point and no intermediate trades get generated even in the presence of non-zero indicative volume at the point of network-wide auction end. (0094-PRAC-005) + +- When market is in a price monitoring auction which is meant to finish at `10am`, but prior to that time a long block auction finishing at 11am gets triggered then the market stays in auction till `11am`, it's auction trigger is listed as price monitoring auction and it's extension trigger is listed as long block auction. (0094-PRAC-006) + +- When a market's `trigger` or `extension_trigger` is set to represent a governance suspension then no other triggers can affect the market. (0094-PRAC-007) + +- When a market's `trigger` and `extension_trigger` are set to represent that the market went into auction due to the price monitoring mechanism and was later extended by the same mechanism and the auction is meant to finish at `11am`, but now a long block auction is being triggered so that it ends at `10am` then this market is unaffected in any way. (0094-PRAC-008) diff --git a/protocol/0095-HVMR-high_volume_maker_rebate.md b/protocol/0095-HVMR-high_volume_maker_rebate.md new file mode 100644 index 000000000..564808b69 --- /dev/null +++ b/protocol/0095-HVMR-high_volume_maker_rebate.md @@ -0,0 +1,70 @@ +# High Volume Maker Rebate + +The high volume maker rebate program is a network-wide community governed set of parameters to provide an additional reward to market makers on the network who are involved in a significant fraction of all trading on the network. When enabled, eligible market makers receive an additional fraction of trading fees from trades in which they are involved on top of any standard received maker fee (and would receive this even were the default maker fee removed). + +## Configuration + +The configuration of the High Volume Maker rebate is performed very similarly to that of the [volume discount program](./0084-VDPR-volume_discount_program.md): +Enabling or changing the terms of the program can be proposed via governance. As part of the proposal, the proposer specifies the following fields: + +- `benefit_tiers`: a list of dictionaries with the following fields + - `minimum_party_maker_volume_fraction`: the required `party_maker_volume_fraction` for a party to access this tier + - `additional_maker_rebate`: the additional rebate factor (in percentage of `trade_value_for_fee_purposes`) a party at this tier will receive when they are the maker side of a trade +- `end_of_program_timestamp`: the timestamp after which when the current epoch ends, the program will become inactive and benefits will be disabled. If this field is empty, the program runs indefinitely. +- `window_length`: the number of epochs over which to measure a party's cumulative maker volume. + + +## Calculation + +For each party, the network must track the maker volume they created in each epoch. + +At the start of an epoch the network should calculate each parties `party_maker_volume_fraction` by calculating what proportion of the maker volume over the last $m$ epochs a party made up (where m is the `window_length` set configured in the program), i.e. + +$$\text{partyMakerVolumeFraction} = \frac{\sum_{i=1}^{m}{V_i}_j}{\sum_{i=1}^{m}\sum_{j=1}^{n}{V_i}_j}$$ + +where: + +- ${V_i}_j$ is the maker volume of party `j` in epoch `i` + + +Each parties `additional_maker_rebate` is then fixed to the value in the highest tier they qualify for. A parties tier is defined as the highest tier for which their `party_maker_volume_fraction` is greater or equal to the tiers `minimum_party_maker_volume_fraction`. If a party does not qualify for any tier, their `additional_maker_rebate` is set to `0`. + +```pseudo +Given: + benefit_tiers=[ + { + "minimum_party_maker_volume_fraction": 0.1, + "additional_maker_rebate": 0.01, + }, + { + "minimum_party_maker_volume_fraction": 0.2, + "additional_maker_rebate": 0.02, + + }, + { + "minimum_party_maker_volume_fraction": 0.3, + "additional_maker_rebate": 0.03, + + }, + ] + +And: + party_maker_volume_fraction=0.23 + +Then: + additional_maker_rebate=0.02 +``` + +This `additional_maker_rebate` factor is then fixed for the duration of the next epoch. + +## Application + +As variable fees for the taker depending upon with whom they are trading would not be a good experience, the additional maker rebate should be taken from a weighted combination of the network treasury and network buyback components of the total fee. The exact calculations are laid out in [0029-FEES](./0029-FEES-fees.md) but are broadly: + + 1. `high_volume_maker_fee = high_volume_factor * trade_value_for_fee_purposes` + 1. `treasury_fee = treasury_fee * (1 - high_volume_maker_fee / (treasury_fee + buyback_fee))` + 1. `buyback_fee = treasury_fee * (1 - buyback_fee / (treasury_fee + buyback_fee))` + +## Governance Requirements + +As the rebate possible level interacts with other fee settings there must be a restriction on it's possible values in governance change proposals. However, as both the rebate and the relevant fees could be changed at once the failure should occur at enactment of the proposal rather than initial validation. The criterion `max(additional_maker_rebate) <= market.fee.factors.treasuryFee + market.fee.factors.buybackFee` should be checked at changes of both the maker rebate program and the two fee factor values to ensure this constraint remains true. diff --git a/protocol/0095-LIQM-liquidity_mechanisms.md b/protocol/0096-LIQM-liquidity_mechanisms.md similarity index 100% rename from protocol/0095-LIQM-liquidity_mechanisms.md rename to protocol/0096-LIQM-liquidity_mechanisms.md diff --git a/protocol/colosseo-features.json b/protocol/colosseo-features.json index daebd7d8b..b1513b3a4 100644 --- a/protocol/colosseo-features.json +++ b/protocol/colosseo-features.json @@ -25,19 +25,29 @@ }, "Isolated margin": { "milestone": "colosseo", - "acs": ["0019-MCAL-208"] + "acs": [ + "0019-MCAL-208" + ] }, "Closeout trades and auctions": { "milestone": "colosseo", - "acs": ["0012-POSR-030"] + "acs": [ + "0012-POSR-030" + ] }, "Market suspended/resumed before enactment": { "milestone": "colosseo", - "acs": ["0043-MKTL-011", "0043-MKTL-012", "0043-MKTL-013"] + "acs": [ + "0043-MKTL-011", + "0043-MKTL-012", + "0043-MKTL-013" + ] }, "Teams": { "milestone": "colosseo", - "acs": ["0083-RFPR-068"] + "acs": [ + "0083-RFPR-068" + ] }, "Spot": { "milestone": "colosseo", @@ -356,64 +366,7 @@ "0056-REWA-167" ] }, - "Spot stretch": { - "milestone": "colosseo", - "acs": [ - "0029-FEES-015", - "0029-FEES-016", - "0029-FEES-017", - "0029-FEES-018", - "0029-FEES-019", - "0029-FEES-020", - "0029-FEES-021", - "0029-FEES-022", - "0049-TVAL-007", - "0049-TVAL-008", - "0049-TVAL-009", - "0049-TVAL-010", - "0049-TVAL-011", - "0049-TVAL-012", - "0051-PROD-004", - "0051-PROD-005", - "0051-PROD-006", - "0052-FPOS-003", - "0052-FPOS-004", - "0054-NETP-007", - "0054-NETP-008", - "0054-NETP-009", - "0054-NETP-010", - "0054-NETP-011", - "0057-TRAN-063", - "0065-FTCO-005", - "0065-FTCO-006", - "0065-FTCO-007", - "0065-FTCO-008", - "0070-MKTD-010", - "0070-MKTD-011", - "0070-MKTD-012", - "0070-MKTD-013", - "0070-MKTD-014", - "0070-MKTD-015", - "0070-MKTD-022", - "0070-MKTD-024", - "0070-MKTD-025", - "0070-MKTD-026", - "0074-BTCH-012", - "0074-BTCH-015", - "0074-BTCH-016", - "0074-BTCH-019", - "0079-TGAP-006", - "0079-TGAP-007", - "0028-GOVE-186", - "0028-GOVE-187", - "0080-SPOT-024", - "0080-SPOT-025", - "0080-SPOT-026", - "0080-SPOT-027", - "0080-SPOT-028", - "0080-SPOT-029" - ] - }, + "Spot stop orders": { "milestone": "colosseo", "acs": [ @@ -528,34 +481,47 @@ "0009-MRKP-037" ] }, - "Perpetual funding rates": { - "milestone": "colosseo", - "acs": ["0053-PERP-036"] - }, "Explicit liquidation range": { "milestone": "colosseo", - "acs": ["0012-POSR-031", "0012-POSR-032", "0012-POSR-033"] + "acs": [ + "0012-POSR-031", + "0012-POSR-032", + "0012-POSR-033"] }, - "Community Tags": { - "milestone": "colosseo", + "Order spam": { + "milestone": "colosseo_II", "acs": [ - "0028-GOVE-168", - "0028-GOVE-169", - "0028-GOVE-170", - "0028-GOVE-171", - "0028-GOVE-172", - "0028-GOVE-173", - "0028-GOVE-174", - "0028-GOVE-175", - "0028-GOVE-176", - "0028-GOVE-177", - "0028-GOVE-178" + "0062-SPAM-043", + "0062-SPAM-044", + "0062-SPAM-045", + "0062-SPAM-047", + "0062-SPAM-048", + "0062-SPAM-049", + "0062-SPAM-050", + "0062-SPAM-051", + "0062-SPAM-052", + "0062-SPAM-053", + "0062-SPAM-054", + "0062-SPAM-055", + "0062-SPAM-056", + "0062-SPAM-057", + "0062-SPAM-058", + "0062-SPAM-059", + "0062-SPAM-060", + "0062-SPAM-061", + "0062-SPAM-062", + "0062-SPAM-063", + "0062-SPAM-064", + "0062-SPAM-066", + "0062-SPAM-067", + "0062-SPAM-068", + "0062-SPAM-069", + "0062-SPAM-070", + "0062-SPAM-071", + "0062-SPAM-072", + "0004-AMND-061" ] }, - "LPs voting without gov token": { - "milestone": "colosseo", - "acs": ["0028-GOVE-185"] - }, "Reward Improvements": { "milestone": "colosseo", "acs": [ @@ -606,8 +572,93 @@ "0057-TRAN-079" ] }, - "vAMMs": { + "Capped Futures": { "milestone": "colosseo_II", + "acs": [ + "0016-PFUT-013", + "0016-PFUT-014", + "0016-PFUT-015", + "0016-PFUT-016", + "0016-PFUT-017", + "0016-PFUT-018", + "0016-PFUT-019", + "0016-PFUT-020", + "0016-PFUT-021", + "0016-PFUT-022", + "0016-PFUT-023", + "0016-PFUT-024", + "0016-PFUT-025", + "0019-MCAL-154", + "0019-MCAL-155", + "0019-MCAL-156", + "0019-MCAL-157", + "0019-MCAL-158", + "0019-MCAL-170", + "0019-MCAL-171" + ] + }, + "Transaction Ordering": { + "milestone": "colosseo_II", + "acs": [ + "0093-TRTO-001", + "0093-TRTO-002", + "0093-TRTO-003", + "0093-TRTO-004", + "0093-TRTO-005", + "0093-TRTO-006", + "0093-TRTO-007", + "0093-TRTO-008", + "0093-TRTO-009", + "0093-TRTO-010", + "0093-TRTO-011", + "0093-TRTO-012", + "0093-TRTO-013", + "0093-TRTO-014", + "0093-TRTO-015", + "0093-TRTO-016", + "0028-GOVE-192", + "0028-GOVE-194", + "0028-GOVE-193" + ] + }, + "Long Block Auction": { + "milestone": "colosseo_II", + "acs": [ + "0026-AUCT-039", + "0026-AUCT-040", + "0094-PRAC-001", + "0094-PRAC-002", + "0094-PRAC-003", + "0094-PRAC-004", + "0094-PRAC-005", + "0094-PRAC-006", + "0094-PRAC-007", + "0094-PRAC-008" + ] + }, + "Model-free alternatives": { + "milestone": "suzuka_castle", + "acs": [ + "0016-PFUT-026", + "0016-PFUT-027", + "0016-PFUT-028", + "0053-PERP-047", + "0053-PERP-048", + "0053-PERP-049", + "0032-PRIM-041", + "0032-PRIM-042", + "0032-PRIM-043", + "0042-LIQF-095", + "0042-LIQF-096", + "0019-MCAL-159" + ] + }, + "Fee mechanic changes": { + "milestone": "suzuka_castle", + "acs": [] + }, + "vAMMs": { + "milestone": "suzuka_castle", "acs": [ "0042-LIQF-092", "0042-LIQF-093", @@ -678,75 +729,20 @@ "0085-RVST-025" ] }, - "Capped Futures": { - "milestone": "colosseo_II", - "acs": [ - "0016-PFUT-013", - "0016-PFUT-014", - "0016-PFUT-015", - "0016-PFUT-016", - "0016-PFUT-017", - "0016-PFUT-018", - "0016-PFUT-019", - "0016-PFUT-020", - "0016-PFUT-021", - "0016-PFUT-022", - "0016-PFUT-023", - "0016-PFUT-024", - "0016-PFUT-025", - "0019-MCAL-154", - "0019-MCAL-155", - "0019-MCAL-156", - "0019-MCAL-157", - "0019-MCAL-158", - "0019-MCAL-170", - "0019-MCAL-171", - "0016-PFUT-029" - ] - }, - "Model-free alternatives": { - "milestone": "colosseo_II", - "acs": [ - "0016-PFUT-026", - "0016-PFUT-027", - "0016-PFUT-028", - "0053-PERP-047", - "0053-PERP-048", - "0053-PERP-049", - "0032-PRIM-041", - "0032-PRIM-042", - "0032-PRIM-043", - "0042-LIQF-095", - "0042-LIQF-096", - "0019-MCAL-159" - ] - }, - "Cancelling Proposals": { - "milestone": "colosseo_II", - "acs": ["0028-GOVE-188", "0028-GOVE-189", "0028-GOVE-190", "0028-GOVE-191"] - }, - "Transaction Ordering": { - "milestone": "colosseo_II", + "Community Tags": { + "milestone": "suzuka_castle", "acs": [ - "0093-TRTO-001", - "0093-TRTO-002", - "0093-TRTO-003", - "0093-TRTO-004", - "0093-TRTO-005", - "0093-TRTO-006", - "0093-TRTO-007", - "0093-TRTO-008", - "0093-TRTO-009", - "0093-TRTO-010", - "0093-TRTO-011", - "0093-TRTO-012", - "0093-TRTO-013", - "0093-TRTO-014", - "0093-TRTO-015", - "0093-TRTO-016", - "0028-GOVE-192", - "0028-GOVE-194", - "0028-GOVE-193" + "0028-GOVE-168", + "0028-GOVE-169", + "0028-GOVE-170", + "0028-GOVE-171", + "0028-GOVE-172", + "0028-GOVE-173", + "0028-GOVE-174", + "0028-GOVE-175", + "0028-GOVE-176", + "0028-GOVE-177", + "0028-GOVE-178" ] }, "Spot AMM": { @@ -762,8 +758,96 @@ "0092-SAMM-008" ] }, + "LP 3.0": { + "milestone": "genbu_temple", + "acs": [] + }, + "Token Buyback auction": { + "milestone": "genbu_temple", + "acs": [] + }, + "Cancelling Proposals": { + "milestone": "historic_distillery", + "acs": [ + "0028-GOVE-188", + "0028-GOVE-189", + "0028-GOVE-190", + "0028-GOVE-191" + ] + }, + + "Perpetual funding rates": { + "milestone": "historic_distillery", + "acs": [ + "0053-PERP-036" + ] + }, + "LPs voting without gov token": { + "milestone": "historic_distillery", + "acs": [ + "0028-GOVE-185" + ] + }, + "Spot stretch": { + "milestone": "historic_distillery", + "acs": [ + "0029-FEES-015", + "0029-FEES-016", + "0029-FEES-017", + "0029-FEES-018", + "0029-FEES-019", + "0029-FEES-020", + "0029-FEES-021", + "0029-FEES-022", + "0049-TVAL-007", + "0049-TVAL-008", + "0049-TVAL-009", + "0049-TVAL-010", + "0049-TVAL-011", + "0049-TVAL-012", + "0051-PROD-004", + "0051-PROD-005", + "0051-PROD-006", + "0052-FPOS-003", + "0052-FPOS-004", + "0054-NETP-007", + "0054-NETP-008", + "0054-NETP-009", + "0054-NETP-010", + "0054-NETP-011", + "0057-TRAN-063", + "0065-FTCO-005", + "0065-FTCO-006", + "0065-FTCO-007", + "0065-FTCO-008", + "0070-MKTD-010", + "0070-MKTD-011", + "0070-MKTD-012", + "0070-MKTD-013", + "0070-MKTD-014", + "0070-MKTD-015", + "0070-MKTD-022", + "0070-MKTD-024", + "0070-MKTD-025", + "0070-MKTD-026", + "0074-BTCH-012", + "0074-BTCH-015", + "0074-BTCH-016", + "0074-BTCH-019", + "0079-TGAP-006", + "0079-TGAP-007", + "0028-GOVE-186", + "0028-GOVE-187", + "0080-SPOT-024", + "0080-SPOT-025", + "0080-SPOT-026", + "0080-SPOT-027", + "0080-SPOT-028", + "0080-SPOT-029" + ] + }, "Unknown": { "milestone": "unknown", "acs": [] } -} +} \ No newline at end of file diff --git a/protocol/cosmic-features.json b/protocol/cosmic-features.json index fa19e42d6..d2c4b31b4 100644 --- a/protocol/cosmic-features.json +++ b/protocol/cosmic-features.json @@ -362,12 +362,9 @@ "0044-LIME-101", "0044-LIME-102", "0026-AUCT-016", - "0026-AUCT-017", "0026-AUCT-018", "0026-AUCT-019", "0026-AUCT-020", - "0026-AUCT-021", - "0026-AUCT-022", "0034-PROB-004", "0042-LIQF-055" ] @@ -465,7 +462,7 @@ "0062-SPAM-037" ] }, -"Rewards": { + "Rewards": { "milestone": "deployment-2", "acs": [ "0085-RVST-001", @@ -558,7 +555,7 @@ "0028-GOVE-152" ] }, - "Batch change proposals": { + "Batch change proposals": { "milestone": "deployment-3", "acs": [ "0028-GOVE-145", @@ -926,18 +923,33 @@ }, "Iceberg Orders": { "milestone": "cosmic-carryover", - "acs": ["0014-ORDT-069"] + "acs": [ + "0014-ORDT-069" + ] }, "Successor Markets": { "milestone": "cosmic-carryover", - "acs": ["0001-MKTF-008"] + "acs": [ + "0001-MKTF-008" + ] }, "Ethereum oracles": { "milestone": "cosmic-carryover", - "acs": ["0082-ETHD-035", "0082-ETHD-041"] + "acs": [ + "0082-ETHD-035", + "0082-ETHD-041" + ] }, "Stop Orders": { "milestone": "cosmic-carryover", - "acs": ["0079-TGAP-004", "0079-TGAP-005", "0014-ORDT-132", "0014-ORDT-133", "0014-ORDT-134", "0014-ORDT-135", "0014-ORDT-136"] + "acs": [ + "0079-TGAP-004", + "0079-TGAP-005", + "0014-ORDT-132", + "0014-ORDT-133", + "0014-ORDT-134", + "0014-ORDT-135", + "0014-ORDT-136" + ] } -} +} \ No newline at end of file diff --git a/wordlist.txt b/wordlist.txt index 990e720be..b396ab1c2 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -229,6 +229,7 @@ PoW PoWs pre precomputed +priori pro protobuf Pseudocode