feat: protocol economics — fee sweep, per-stream fees, referrals, insurance pool - #536
Merged
Chuks-coderr merged 2 commits intoAug 31, 2026
Conversation
…urance pool Implements issues SoroStream#462, SoroStream#463, SoroStream#464, SoroStream#465. - SoroStream#465: `set_fee_recipient`/`get_fee_recipient` plus a reworked `sweep_fees` that pays out to the configured recipient instead of an arbitrary caller-supplied destination, so a sweep can't be redirected off-protocol. - SoroStream#462: `set_stream_fee_override`/`clear_stream_fee_override`/ `get_stream_fee_override` let the admin set a custom basis-point fee rate for a specific stream (tiered pricing), applied ahead of the token fee tier and the global protocol fee at every withdrawal path. - SoroStream#464: `set_stream_referral` (sender-only) attributes a referral address to a stream; `set_referral_fee_share` (admin) configures what fraction of the *protocol fee* (not principal) is routed to the referral, settled atomically on-chain at withdrawal time via a shared `settle_protocol_fee` helper. `get_referral_rewards` exposes the running total per referral/token. - SoroStream#463: `set_insurance_bps` funds a per-token insurance reserve from an additional sender-paid contribution at stream creation (additive, not deducted from the streamed deposit). `cancel_stream_as_failure` lets the admin/guardian cancel a stream on a contract-verified failure and compensate the recipient's unvested shortfall from the reserve, capped to `insurance_bps` of the deposit and to the reserve balance — funded by the protocol, not clawed back from the sender. New storage.rs sections follow the existing "moved out of Stream struct" pattern (see `stream_tag`) rather than adding Stream fields, since the struct was already at Soroban's 40-field cap. Pre-existing baseline fixes (unrelated to SoroStream#462-SoroStream#465, needed before any of the above could compile or be tested — main was broken before this branch): - `StreamError` had 59 variants (duplicate names/values); Soroban's `#[contracterror]` caps it at 50. Deduped and trimmed unused variants. - `Stream` had 42 fields; Soroban's `#[contracttype]` caps structs at 40. Moved `on_complete_contract`/`on_complete_function` to separate persistent storage (same treatment `stream_tag` already got), matching the existing pattern in this file. - `create_stream` had grown to 12 non-`env` parameters against Soroban's 10-parameter contract-function limit. Bundled the three least-central flags into a new `StreamCreateOptions` struct. - Several call-site/import/argument-count mismatches in `lib.rs` and `interface.rs` left over from a prior merge (undeclared imports, wrong arg counts, `std`-only `Vec` API used on `soroban_sdk::Vec`, an `Option<StreamStatus>` field that Soroban's `testutils` XDR conversion doesn't support for user-defined enums). - `integration_tests.rs`/`rate_limit_tests.rs` are disabled (commented out in `lib.rs`, alongside the already-disabled `test.rs`/`feature_tests.rs`/ etc.): they target a stale `create_stream`/fee API from before this regression and are unrelated to SoroStream#462-SoroStream#465. Left for a maintainer to reconcile separately, per explicit direction on this PR. - Fixed the pre-existing clippy warnings the above changes exposed (`cargo clippy --workspace --all-targets` is now clean). Verified: `cargo test --workspace` passes (13 new tests covering all four issues), `cargo clippy --workspace --all-targets` is clean, and `cargo build --target wasm32v1-none --release` succeeds. Closes SoroStream#462 Closes SoroStream#463 Closes SoroStream#464 Closes SoroStream#465 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
@anitajordan22244-afk 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! 🚀 |
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.
Implements #462, #463, #464, #465.
What's included
set_fee_recipient/get_fee_recipientplus a reworkedsweep_feesthat pays out to the configured recipient instead of an arbitrary caller-supplied destination, so a sweep can't be redirected off-protocol. Admin-only, emitsFeeSweptwith the amount and destination.set_stream_fee_override/clear_stream_fee_override/get_stream_fee_overridelet the admin set a custom basis-point fee rate for a specific stream (tiered pricing), applied ahead of the token fee tier and the global protocol fee at every withdrawal path.set_stream_referral(sender-only) attributes a referral address to a stream;set_referral_fee_share(admin) configures what fraction of the protocol fee (not principal) is routed to the referral, settled atomically on-chain at withdrawal time.get_referral_rewardsexposes the running total per referral/token.set_insurance_bpsfunds a per-token insurance reserve from an additional sender-paid contribution at stream creation (additive, not deducted from the streamed deposit).cancel_stream_as_failurelets the admin/guardian cancel a stream on a contract-verified failure and compensate the recipient's unvested shortfall from the reserve, capped toinsurance_bpsof the deposit and to the reserve balance — funded by the protocol, not clawed back from the sender.New storage lives in
storage.rsfollowing the existing "moved out ofStreamstruct" convention already used forstream_tag, rather than adding fields toStream— see below.Pre-existing baseline fixes (unrelated to #462–#465)
maindid not compile before this branch. Since all four issues need to build and have passing tests, I fixed what was necessary to unblock that, kept to the minimum:StreamErrorhad 59 variants with duplicate names/values; Soroban's#[contracterror]caps it at 50. Deduped and trimmed unused variants back under the cap.Streamhad 42 fields; Soroban's#[contracttype]caps structs at 40. Movedon_complete_contract/on_complete_functionto separate persistent storage (same treatmentstream_tagalready got).create_streamhad grown to 12 non-envparameters against Soroban's 10-parameter contract-function limit. Bundled the three least-central flags into a newStreamCreateOptionsstruct.lib.rsandinterface.rsleft over from a prior merge (undeclared imports, wrong arg counts,std-onlyVecAPI used onsoroban_sdk::Vec, anOption<StreamStatus>field that Soroban'stestutilsXDR conversion doesn't support for user-defined enums).integration_tests.rs/rate_limit_tests.rsare now disabled (commented out inlib.rs, alongside the already-disabledtest.rs/feature_tests.rs/ etc.): they target a stalecreate_stream/fee API from before this regression (e.g. calls to aset_creation_taxfunction that no longer exists) and are unrelated to Implement per-stream fee override to allow premium streams with custom fee rates #462–Add stream treasury entry point to sweep protocol fees to a configurable fee recipient address #465. Left for a maintainer to reconcile separately — happy to take that on as its own PR if useful.cargo clippy --workspace --all-targetsis now clean.Verification
cargo test --workspace— passes, including 13 new tests covering all four issues (contracts/stream/src/protocol_economics_tests.rs)cargo clippy --workspace --all-targets— cleancargo build --target wasm32v1-none --release— succeedsCloses #462
Closes #463
Closes #464
Closes #465
🤖 Generated with Claude Code