Repository navigation
[CLOB-084, CLOB-085, CLOB-087, CLOB-017] Quote rounding, maker and taker fees, and state ownership - #1100
Merged
IbrahimIjai merged 3 commits intoOct 21, 2026
Conversation
Replace QuoteCalculator with quote_atoms and fill_quote_legs, which follow protocol spec sections 4.2 and 7.2: bid locks and buyer debits round up, seller credits round down, and the difference is the dust residue. Drop the Nearest mode and calculate_dust. The spec defines neither, and dust was computed in scaled units rather than quote atoms. Nothing in the repository called either. Tests reproduce spec Examples B and C and check that splitting a bid does not change its total debit or credit.
Maker fees (SO4-Markets#961): MarketFeeConfig stores a maker_fee_rate next to the taker rate. Both are validated against MAX_FEE_RATE and must be non-negative, so maker rebates stay out of scope for v1. A maker fee is taken from the maker's quote leg, and a zero fee leaves no liability entry. Bid reservation now covers the larger of the maker and taker fees, because a resting bid can fill as a maker later. Taker fees across fragments (SO4-Markets#963): the taker fee for a fill is the difference of rounded-up fees on the taker's running total, so fills split across several makers pay the same as one fill. Settlement takes taker_quote_before for that running total. Also updates protocol spec section 2, which listed all trading fees as a v1 non-goal, and rewrites docs/fee-accounting.md with the formulas and test vectors.
Choose a per-market contract topology for v1: one market contract owns its orders, book, balances, dust account, and fee accumulators, and one registry creates market instances and owns the market list. Trading makes no cross-contract call, and custody is never shared across markets. The document names the owner and writer of every state item, the call paths for deposit, withdrawal, trading, fee withdrawal, market creation, and reads, and the deployment implications for upgrades, immutable parameters, blast radius, and resource limits. SO4-Markets#892 is still open, so this topology is a recommendation pending its outcome.
|
@medunrebecca-dot Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #960
Closes #961
Closes #963
Closes #893
Summary
One branch for four Stellar Wave issues, in
libs/clob_settlement_coreanddocs/:QuoteCalculatoris replaced byquote_atomsandfill_quote_legs, which follow protocol spec sections 4.2 and 7.2. Bid locks and buyer debits round up, seller credits round down, and the difference is the dust residue. TheNearestmode andcalculate_dustare removed, because the spec defines neither. Tests reproduce spec Examples B and C, and check that splitting a bid does not change its total debit or credit or let seller credit grow.MarketFeeConfigstoresmaker_fee_ratebeside the taker rate. Both rates must lie in[0, MAX_FEE_RATE], so maker rebates stay out of scope for v1. The maker fee comes from the maker's quote leg, and a zero fee records no liability. A bid's reservation covers the larger of the maker and taker fees, because a resting bid can fill as a maker later.taker_quote_beforefor the running total.docs/clob-state-ownership.mdchooses a per-market topology: one market contract owns its book, balances, dust, and fee accumulators, and one registry creates market instances. Trading makes no cross-contract call.Also updated:
docs/fee-accounting.md(formulas, settlement legs, test vectors) anddocs/protocol.mdsection 2. That section listed all trading fees as a v1 non-goal, which conflicts with #961 and #963.Decisions to confirm
docs/clob-state-ownership.mdis a recommendation. It also resolves the [CLOB-029] Support deposits independent of a single market when assets are reused #905 TODOs incontracts/reader/src/clob_reads.rsby choosing per-market custody, not shared custody.MAX_FEE_RATEequalsFEE_RATE_SCALE(100%), the bound the code already enforced. A lower protocol maximum is a product decision, so I did not invent one.0 <= residue <= 1. The spec wording should be fixed separately.Verification
Cargo.toml,AGENTS.md, or SDK package, so the verification gate named in the issues cannot run here. The SDK part of [CLOB-084] Align SDK preview arithmetic and prevent fragmentation rounding gains #960 ("identical amounts") is covered by the test vectors indocs/fee-accounting.mdand the unit tests, and needs an SDK package to be checked end to end.lib.rsimportsi128fromsoroban_sdkand usesVecwithout importing it, which will not compile in ano_stdcrate. The CI workflow'scargo fmt --checkalso fails on lines that predate this PR. I did not touch these, so this PR does not make them worse, but they need fixing before CI can pass.