Repository navigation
Constrained, admin-configured protocol fee recipients - #1092
IbrahimIjai merged 11 commits into
Conversation
main did not compile, so no gate step could run: - tests/Cargo.toml: two [[test]] headers were missing (duplicate keys) - settlement_invariants/rollback_harness: depended on nonexistent `gmx_types`/`gmx_math` package names; fixed unused-arg/while-let/clippy issues, a nonexistent `soroban_sdk::Status`, a u32/u64 mismatch, an invalid `Env::new()` call, and a test asserting on a nonexistent field - gmx-types event_schema: `[u8; 32]` is not a contracttype; use BytesN<32> - order_cleanup: u32/usize comparison in the batch limit check - cargo fmt on the touched modules Compile fixes only; no behaviour changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Protocol fees could be paid to any address the FEE_KEEPER passed to
claim_fees / claim_all_fees. The destination is now trusted state only.
- Protocol recipient (instance storage) set by `set_fee_receiver`, and an
optional per-market override (persistent storage) set/cleared by
`set_market_fee_receiver`; both stored-admin only.
- Every change emits `FeeReceiverSet { market, previous, receiver }`
(topic `fee_rcv`) so the full history is auditable.
- BREAKING: `claim_fees(keeper, market, token)` and
`claim_all_fees(fee_handler, keeper, markets, tokens)` drop the
`receiver` argument; `BatchFeesClaimed` drops its `receiver` field.
- Reverts with FeeReceiverNotSet (SO4-Markets#7) when nothing is configured, and
InvalidFeeReceiver (SO4-Markets#8) for the market pool or the handler itself.
- New views: get_fee_receiver, get_protocol_fee_receiver,
get_market_fee_receiver. v1 is single-recipient; no splits.
- Accrual paths are unchanged: settlement credits
claimable_fee_amount(market, token); no order parameter is consulted.
Tests: unit tests for routing, fallback, admin auth (positive/negative),
invalid recipients, events; sweeper per-market routing; e2e test showing
an order's `receiver` cannot redirect settled fees; fee scenarios added
to the resource bench. Docs: security.md, deployment.md, auth-audit.md;
deploy.sh sets the protocol recipient after initialize.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pre-existing test code that never compiled or that current stable clippy (what CI installs) rejects; no production behaviour changes: - order_handler tests from SO4-Markets#1086 (rollback_atomicity, settlement_invariants): add the missing settlement_invariants/rollback_harness dev-dependencies, drop an extra `initialize` argument, fix a u32/u64 comparison and a use-after-move, remove unused imports, rustfmt - tests/clob_model.rs (SO4-Markets#1082): type alias for a complex return type, needless borrows, `div_ceil` - oracle: turn an assertion on a constant into a compile-time check Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Picks up the new fee-recipient entrypoints, the `receiver`-less claim_fees / claim_all_fees signatures, and errors SO4-Markets#7/SO4-Markets#8. Generated with stellar-cli 28.1.0. The package.json bump to @stellar/stellar-sdk ^16 that this CLI version emits was left out on purpose (major frontend upgrade, out of scope); other contracts' bindings are stale only because of SO4-Markets#1085's gmx-types additions and are untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
execute_{deposit,withdrawal}_reverts_on_stale_price advanced the ledger by
one and expected a panic, but oracle#1205 (53abcfb) deliberately accepts
prices for PRICE_FRESHNESS_WINDOW (20) ledgers, so the calls succeed and
the #[should_panic] tests fail. Step past the window so the tests check
what they describe again. Test-only change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds fees/set_fee_receiver, fees/set_market_fee_receiver and fees/claim_fees. Every existing scenario is unchanged versus the previous baseline. Recorded from CI run 39335378079 (ubuntu, soroban-sdk 25.3.1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`cargo build --target wasm32v1-none --release` with no -p list builds every workspace member, including test-only crates that enable soroban-sdk `testutils`, which does not compile for wasm. Use `make build-wasm` (the $(CONTRACTS) list), as ci.yml already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The FIFO property test picks resting orders at random to cancel or reduce,
and reduces to rng.range(1, qty - 1). Once an order has been reduced to 1,
choosing it again calls range(1, 0) and underflows ("attempt to subtract
with overflow"). Cancel it instead in that case. Generator bug in the test
only; this test never ran before because tests/Cargo.toml was missing its
[[test]] header.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Heads-up for maintainers: the conflicts on this PR are not from this branch. #1090 (merge commit You can check it with: This branch merged cleanly with I haven't resolved the conflicts here, because accepting |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Markets#1090 deleted SO4-Markets#1090 (280f268) deleted 765 files from main, leaving only libs/clob_settlement_core. This merge keeps this branch's full tree, which restores every file SO4-Markets#1090 deleted, and takes the files main added since 5436392 (SO4-Markets#1090, SO4-Markets#1083, SO4-Markets#1089, SO4-Markets#1084): - libs/clob_settlement_core/src/lib.rs - contracts/reader/src/clob_reads.rs - docs/REENTRANCY_ANALYSIS.md, docs/clob-read-api-specification.md, docs/market-data-streaming.md - tests/reentrancy_token.rs None of these are compiled yet: clob_settlement_core has no Cargo.toml, clob_reads.rs is not declared as a module, and reentrancy_token.rs is not registered in tests/Cargo.toml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@toluwalasedaniel459-cmyk 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! 🚀 |
Closes #969
Summary
Protocol fees could be paid to any address the FEE_KEEPER passed to
claim_fees/claim_all_fees. The destination is now trusted configuration only.fee_handlerstorage: a protocol-wide recipient (set_fee_receiver) and an optional per-market override for issuer/partner payouts (set_market_fee_receiver(market, Some(r) | None)). Both require the stored admin's auth.FeeReceiverSet { market, previous, receiver }(topicfee_rcv).claim_fees(keeper, market, token)andclaim_all_fees(fee_handler, keeper, markets, tokens)no longer takereceiver.FeeReceiverNotSet(#7 — Create a config key catalog #7) when nothing is configured (fees stay claimable);InvalidFeeReceiver(#8 — Create an event catalog #8) for the market pool or the handler itself, checked at set time and at claim time.get_fee_receiver(market)(effective),get_protocol_fee_receiver(),get_market_fee_receiver(market).claimable_fee_amount(market, token)alongsidepool_amount; no order parameter is consulted for the fee destination. The resource benchmark confirms every existing lifecycle scenario is byte-for-byte unchanged.claim_feesandclaim_all_feessignatures changed;BatchFeesClaimeddropped itsreceiverfield. Frontend/keeper callers must update. TS bindings forfee-handlerandfee-batch-sweeperare regenerated.fee_handler, the admin must callset_fee_receiver— claims revert until then.scripts/deploy.shnow sets it on fresh deploys (FEE_RECEIVER, default$ADMIN).InstanceKey::ProtocolFeeReceiver,PersistentKey::MarketFeeReceiver(market). No migration of existing data needed.Commits
152628fd8485b1a48ab0aclippy --all-targets -D warningspass (#1086 order_handler tests that never compiled, #1082clob_modellints, anoracleconstant assertion)bd16f92fee-handler/fee-batch-sweeperbindings43603436c127fbca1ef17fees/*scenarios (from CI run 39335378079)a3d265bwasm-size.ymlbuilds only deployable contracts (make build-wasm)799c591clob_propertiesgenerator could reduce an order already at qty 1 and underflow3053843mainup to #1088 (5436392, before #1090)4233d6bmain, keeping the full tree (restores files #1090 deleted) and taking the 6 files added sinceBranched from
1e6ca2fand merged withmain(see the note at the top). #1087/#1088 add docs andlibs/typesfiles that are not yet declared as modules, so they don't affect the build.The pre-existing fixes are separate commits so they can be reviewed or cherry-picked independently; none change production behaviour.
Tests
fee_handlerunit tests: routes to the configured recipient only (keeper gets nothing); no recipient → revert with fees/pool accounting untouched; market override + clear → fallback; admin-auth positive and negative paths for both setters; invalid recipients rejected; audit events with previous/new values.fee_batch_sweeper: each market in a batch pays its own configured recipient.tests/fee_receiver_routing.rs(e2e): an executed order whosereceiveris an attacker address still pays the settled fee to the treasury; a market override receives it instead of the treasury.tests/resource_bench.rs:fees/set_fee_receiver,fees/set_market_fee_receiver,fees/claim_fees.CI status (at
799c591, run on the fork toluwalasedaniel459-cmyk#1)-D warnings)stellar contract buildlocally)tests/funding_rate.rs, see belowmain) build fails becausemaindoes not compile until this PR mergescargo testpassing before it stops: every contract and lib crate, includingfee_handler(34) andfee_batch_sweeper(7); and the integration tests includingfee_receiver_routing(both tests),funding_conservation_e2e,clob_model,clob_properties. Becausecargo teststops at the first failing binary, test files afterfunding_ratehave not run on CI yet.After the merge with
main(4233d6b, fork CI runs 39450558514 and 39450566536): rustfmt, clippy, the WASM build and Resource Benchmarks pass again.cargo testfails only on the same 6funding_ratetests.tests/funding_rate.rs(6 of 7 fail) — needs a maintainer decisionThese tests are in funding money-path code this PR does not touch. They had not run since
mainstopped compiling, and they now disagree withlibs/market_utils. Per AGENTS.md I have not changed either side; someone needs to decide whether the code or the tests are wrong.Failures:
funding_rate_zero_when_no_oi(factor 3600, expected 0),funding_rate_longs_pay_shorts_when_long_oi_exceeds_shortand…shorts_pay_longs…(funding per size 0),test_funding_rate_accumulation_and_settlement_integration,funding_settlement_accumulates_claimable_amount,funding_rate_zero_when_oi_balanced.Findings:
compute_next_funding_factorcaps the per-tick change atmul_div_wide(increase_factor, dt, FLOAT_PRECISION). With the tests' "100% per second" setting (increase_factor = FLOAT_PRECISION), the cap over one hour isdt= 3600 raw units (3.6e-27), so funding per size rounds to 0. GMX appliesfundingIncreaseFactorPerSecond * durationInSecondswith no division. If the division is wrong, funding barely ramps on-chain either. This dates from the original market-utils commit (4b16a66).funding_conservation_e2epasses only because it sets the ramp to1000 * FLOAT_PRECISION.funding_exponent_factor = 1(raw); the passing conservation test usesFLOAT_PRECISION, which suggests the exponent's units changed and these tests weren't updated.funding_rate_zero_when_no_oiexpects a zero factor right after a full close, but funding state is updated at the start of the closing order, while OI is still non-zero, so a non-zero factor legitimately remains until the next update.Suggest tracking (1) as its own issue; (2) and (3) look like stale tests.
Not covered by CI
make deploy-all/make testnet-smoke(deploy path changed inscripts/deploy.sh) have not been run.gmx-typesadditions (event/state/error types now in every spec); left untouched. The CLI's@stellar/stellar-sdk^14→^16package.jsonbump was intentionally not included.🤖 Generated with Claude Code