| type | Feature |
|---|---|
| title | Add a lower-only admin entrypoint to reduce the protocol fee bps after init |
| labels | type:feature, area:protocol-fee, stack:soroban, stack:rust, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 |
| assignees |
protocol_fee_bps is written once in init() under DataKey::ProtocolFeeBps and is read by withdraw() to size the treasury cut, but no entrypoint can ever change it. Add lower_protocol_fee_bps(new_bps) so an admin can only ever reduce the fee, mirroring the forward-only guard style already used by lower_min_contribution_floor and lower_max_unique_investors.
- Repository scope: Liquifact/Liquifact-contracts only.
- Reject any
new_bpsgreater than or equal to the value returned byget_protocol_fee_bps()with a typedEscrowError, and reject values outside0..=10_000. - Gate the call on admin
require_auth()and emit a structured#[contractevent]carrying the old and new bps. - Allow the reduction only before the escrow reaches
withdrawn, so an already-disbursed escrow cannot be retroactively re-priced.
- Fork the repo and create a branch
git checkout -b feature/contracts-lower-protocol-fee- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
feat(escrow): add lower-only protocol fee bps update entrypoint
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Add a protocol-fee preview view reporting the treasury cut and SME net before withdraw" labels: type:feature, area:read-api, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
withdraw() computes fee = funded_amount * protocol_fee_bps / 10_000 inline and splits the disbursement between the treasury and the SME, but integrators cannot see that split until the transaction lands. Add a preview_protocol_fee() view returning both legs using the same checked arithmetic path.
- Repository scope: Liquifact/Liquifact-contracts only.
- Return a struct (or tuple) with the computed fee and the SME net amount, derived from
funded_amountandDataKey::ProtocolFeeBps. - Reuse the exact rounding used in
withdraw()so the preview never disagrees with the executed split by even one stroop. - Keep the view read-only and callable in any status, returning zeros when
funded_amountis zero.
- Fork the repo and create a branch
git checkout -b feature/contracts-protocol-fee-preview- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
feat(escrow): add preview_protocol_fee read view
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Add a batch claimable-payout view returning many investors' pending amounts in one call" labels: type:feature, area:read-api, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
get_claimable_payout(investor) answers for a single address, forcing indexers to issue one simulation per investor across a large cap table. Add get_claimable_payouts(investors: Vec<Address>) -> Vec<i128> that mirrors the batching already provided by get_contributions.
- Repository scope: Liquifact/Liquifact-contracts only.
- Preserve per-entry ordering so index
iof the output corresponds to indexiof the input. - Bound the input length with a
MAX_*_BATCHconstant and a typed error, matching the batch guards used byset_investors_allowlisted. - Return
0for unknown investors and for investors already flagged byis_investor_claimed, exactly as the single-address view does.
- Fork the repo and create a branch
git checkout -b feature/contracts-batch-claimable-payouts- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
feat(escrow): add get_claimable_payouts batch read view
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Extend EscrowSummary with the pause flag and the configured protocol fee bps" labels: type:enhancement, area:read-api, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
get_escrow_summary() aggregates the fields an indexer needs in one round-trip, but it omits the global pause switch read by is_paused() and the fee read by get_protocol_fee_bps(). Clients must therefore make two extra calls to render accurate escrow state.
- Repository scope: Liquifact/Liquifact-contracts only.
- Add
paused: boolandprotocol_fee_bps: i64to theEscrowSummarystruct as additive fields. - Populate them from the same storage keys the standalone views use so the summary can never drift.
- Update
docs/escrow-read-api.mdand add a test asserting the summary fields trackset_pausedand the init-time fee.
- Fork the repo and create a branch
git checkout -b enhancement/contracts-summary-pause-fee- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
feat(escrow): extend EscrowSummary with pause and protocol fee fields
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Emit a dedicated protocol-fee event from withdraw recording the treasury cut" labels: type:enhancement, area:events, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
withdraw() transfers the protocol fee to DataKey::Treasury and the remainder to the SME, but the fee leg is not separately observable on-chain. Accounting integrations have to re-derive it from funded_amount and the fee bps rather than reading a topic.
- Repository scope: Liquifact/Liquifact-contracts only.
- Add a
#[contractevent]struct carrying the fee amount, the effective bps, the treasury address, and the SME net amount. - Emit it from
withdraw()only when the computed fee is non-zero, keeping the zero-fee path byte-identical to today. - Use a
symbol_short!topic that collides with no existing emitter and register it indocs/EVENT_SCHEMA.md.
- Fork the repo and create a branch
git checkout -b enhancement/contracts-protocol-fee-event- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
feat(escrow): emit protocol fee event from withdraw
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Bound the bump_ttl allowlisted vector length to cap per-call storage work" labels: type:security, area:storage-ttl, stack:soroban, stack:rust, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
bump_ttl(env, allowlisted: Vec<Address>) is permissionless and iterates the caller-supplied vector to extend per-investor persistent keys, but the vector length is unbounded. A caller can pass an arbitrarily large list and drive the instruction and storage-access budget to the ledger limit on every invocation.
- Repository scope: Liquifact/Liquifact-contracts only.
- Introduce a
MAX_BUMP_TTL_BATCHconstant and reject longer inputs with a typedEscrowError, matchingMAX_INVESTOR_ALLOWLIST_BATCHandMAX_ATTESTATION_REVOKE_BATCH. - Keep the entrypoint permissionless β the cap is the mitigation, not an auth gate.
- Add tests at the cap boundary, one entry over the cap, and with an empty vector.
- Fork the repo and create a branch
git checkout -b security/contracts-cap-bump-ttl-batch- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
fix(escrow): bound bump_ttl batch length with a typed error
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Disambiguate the att_rev event symbol shared by single and batch attestation revocation" labels: type:security, area:events, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
revoke_attestation_digest and revoke_attestation_digests both emit events under symbol_short!("att_rev"). Indexers subscribing to that topic cannot distinguish a single targeted revocation from an entry inside an operator batch, which weakens the compliance audit trail these digests exist to provide.
- Repository scope: Liquifact/Liquifact-contracts only.
- Give the batch emitter its own topic (for example
att_revb) or add a discriminating field to the event payload. - Verify no other emitter reuses the chosen symbol before landing the change.
- Add a test asserting the two entrypoints publish distinguishable topics, and update
docs/escrow-attestations.md.
- Fork the repo and create a branch
git checkout -b security/contracts-att-rev-symbol- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
fix(escrow): disambiguate single and batch attestation revocation event topics
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Collapse the duplicated coll_clr event emitted twice by clear_sme_collateral_commitment" labels: type:refactor, area:events, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
clear_sme_collateral_commitment() publishes two separate events that both use symbol_short!("coll_clr"). Downstream consumers see the same logical clear twice per call and cannot tell which payload is authoritative.
- Repository scope: Liquifact/Liquifact-contracts only.
- Determine which of the two emissions is the intended record and remove or rename the redundant one.
- Preserve every field currently observable to indexers so the change is additive from a consumer's point of view.
- Add a test asserting exactly one
coll_clrevent is published per successful clear.
- Fork the repo and create a branch
git checkout -b refactor/contracts-coll-clr-duplicate- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
refactor(escrow): remove duplicate coll_clr event emission
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Extract the repeated start and limit pagination bounds logic into a shared helper" labels: type:refactor, area:read-api, stack:soroban, stack:rust, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
get_investors, get_allowlisted_investors, and get_revoked_attestation_digests each re-implement the same start/limit window clamping against a backing length. The duplicated arithmetic is the kind of code where one path silently drifts into an off-by-one or an underflow.
- Repository scope: Liquifact/Liquifact-contracts only.
- Add a private helper returning the resolved
(start, end)window for a given collection length, with saturating arithmetic. - Rewrite all three paginated views to call it, leaving their public signatures and return types unchanged.
- Add unit tests for
startpast the end, zerolimit, and alimitexceeding the remaining items.
- Fork the repo and create a branch
git checkout -b refactor/contracts-pagination-helper- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
refactor(escrow): centralize paginated view window clamping
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Add tests for the global pause switch gating fund, settle, withdraw, and claim" labels: type:test, area:pause, stack:soroban, stack:rust, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
set_paused() writes the pause flag surfaced by is_paused(), but there is no test matrix proving the flag actually blocks the value-moving entrypoints. Without it a refactor could drop a pause check from fund, settle, withdraw, or claim_investor_payout and no test would fail.
- Repository scope: Liquifact/Liquifact-contracts only.
- Assert each value-moving entrypoint fails with the expected typed
EscrowErrorwhile paused, and succeeds after unpausing. - Assert read-only views such as
get_escrowandget_escrow_summaryremain callable while paused. - Assert
set_pausedis admin-gated and that a redundant no-op call is handled as documented.
- Fork the repo and create a branch
git checkout -b test/contracts-pause-gating-tests- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
test(escrow): add pause switch gating matrix
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Add tests for get_reconciliation balance-versus-liability accounting across the lifecycle" labels: type:test, area:reconciliation, stack:soroban, stack:rust, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
get_reconciliation() returns a ReconciliationView comparing the live funding-token balance against outstanding liabilities, and sweep_terminal_dust relies on the same liability floor. The view has no dedicated test coverage across the states it is meant to describe.
- Repository scope: Liquifact/Liquifact-contracts only.
- Cover a fresh escrow, a partially funded escrow, a fully funded escrow, and post-settlement after some investors have claimed.
- Assert the view's liability figure tracks
funded_amountminusget_distributed_principal()at every step. - Include a cancelled-and-partially-refunded escrow and assert the surplus reported matches what
sweep_terminal_dustwould permit.
- Fork the repo and create a branch
git checkout -b test/contracts-reconciliation-tests- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
test(escrow): cover get_reconciliation across the escrow lifecycle
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Add tests for get_settlement_readiness field-by-field against maturity and legal hold" labels: type:test, area:settlement, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
get_settlement_readiness() bundles settleability, legal-hold state, and maturity into a single SettlementReadiness struct, but nothing asserts each field independently against the underlying predicates such as is_settleable() and get_legal_hold().
- Repository scope: Liquifact/Liquifact-contracts only.
- Assert every field matches its standalone view across pre-maturity, post-maturity, held, and already-settled escrows.
- Cover the zero-maturity and
has_maturity_lock()false configurations explicitly. - Assert the struct never reports settleable while a legal hold is active.
- Fork the repo and create a branch
git checkout -b test/contracts-settlement-readiness-tests- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
test(escrow): assert settlement readiness fields against source predicates
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Add proptests asserting the protocol fee plus the SME net always equals the disbursed principal" labels: type:test, area:protocol-fee, stack:soroban, stack:rust, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
withdraw() floors the protocol fee and leaves the rounding residue with the SME, so no value should ever be created or lost in the split. This conservation property is asserted only by hand-picked examples today, not across the input space.
- Repository scope: Liquifact/Liquifact-contracts only.
- Generate random
funded_amountandprotocol_fee_bpspairs across the full valid ranges including the0and10_000endpoints. - Assert
fee + sme_net == funded_amountexactly, thatfeeis never negative, and thatfeenever exceedsfunded_amount. - Assert the treasury and SME balance deltas after
withdraw()match the computed legs.
- Fork the repo and create a branch
git checkout -b test/contracts-fee-split-proptest- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
test(escrow): add proptest for protocol fee split conservation
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Document the global pause switch and its precedence over the compliance legal hold" labels: type:docs, area:pause, stack:soroban, stack:rust, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
The contract now carries two independent freeze mechanisms β set_paused/is_paused and the timelocked legal hold behind set_legal_hold, request_clear_legal_hold, and clear_legal_hold_after_delay. Operators have no single document explaining which one to reach for or what happens when both are active.
- Repository scope: Liquifact/Liquifact-contracts only.
- Write
docs/escrow-pause.mdcovering who can pause, which entrypoints are blocked, and how unpausing differs from clearing a hold. - State the precedence when both are active and which typed
EscrowErrorsurfaces in that case. - Cross-link
docs/escrow-legal-hold.mdand theOPERATOR_RUNBOOK.mdincident procedure.
- Fork the repo and create a branch
git checkout -b docs/contracts-document-pause-switch- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
docs(escrow): document the global pause switch and legal-hold precedence
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated. ++++++
type: Feature title: "Document the pagination contract shared by every start and limit read view" labels: type:docs, area:read-api, stack:soroban, stack:rust, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN, Official Campaign | FWC26 assignees: ''
get_investors, get_allowlisted_investors, and get_revoked_attestation_digests all take (start, limit) but their exact semantics β clamping, ordering stability, and behavior when start is past the end β are not written down anywhere. Indexer authors currently have to read lib.rs to page safely.
- Repository scope: Liquifact/Liquifact-contracts only.
- Add a pagination section to
docs/escrow-read-api.mdspecifying the half-open window, clamping rules, and the maximumlimithonored. - State whether ordering is stable across ledger writes and how a caller should detect the final page.
- Include a worked paging loop example and cross-link
docs/escrow-indexer.md.
- Fork the repo and create a branch
git checkout -b docs/contracts-document-pagination-contract- Write code in:
escrow/src/lib.rs - Write comprehensive tests in:
escrow/src/tests.rs - Add documentation: README / docs
- Include NatSpec-style
///comments
- Run
cargo fmt --all -- --check,cargo build,cargo test - Cover edge cases and failure paths
docs(escrow): document the shared start/limit pagination contract
- Minimum 95 percent test coverage for impacted modules
- Clear documentation
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β a 5-star rating is much appreciated.