Repository navigation
[DeFi][FIN-20] Separate dynamic liquidity fees, protocol fees and extension charges #70
Description
Parent programme: #43. Capability work-item FIN-20 (proposed; no new compiler/release commitment).
In plain English
Trading fees can go to liquidity providers, a configured protocol beneficiary or an authorised extension. Each component needs separate limits and cannot quietly consume somebody else's underlying reserves.
Visual explanation
flowchart LR
A["Static/dynamic fee policy"] --> B["Authorised update or per-trade override"]
B --> C["Price and fee calculation"]
C --> D["LP fees / protocol fees / hook charge"]
D --> E["Correct beneficiary balances"]
Primary layer: Pool fee policy, authority and hook integration.
Dependencies: #64 FIN-14 fee-growth state; #66 FIN-16 delta settlement; #69 FIN-19 authenticated hooks.
Detailed design and security review
Accounting model: three independent fee authorities
The pool liquidity-provider fee belongs economically to eligible position holders. A protocol charge belongs only to its declared beneficiary and must be taken under a separately authenticated policy. A hook's charge or rebate is an additional transaction obligation and must have separately granted delta authority. A single generic fee variable cannot explain all three. Freeze who may configure each, the exact units, denominator, precision, minimum/maximum, allocation order and rounding.
Static configuration versus dynamic decisions
Specify the immutable choice between fixed fee and dynamically managed fee at pool creation. A persistent dynamic-fee update requires the authorised governance/hook state transition; a per-swap override is a different scoped permission and must bind the current operation only. Determine the result when a fee effectively consumes the entire input: such a configuration cannot silently claim an exact-output swap succeeded. Explicitly choose the interaction between base fees, optional protocol share, hook-originated extra charge and previously accumulated fee liabilities.
Implementation phases
- Publish independent fee equations with typed signed/unsigned domains and example before/after balances.
- Implement static and separately authorised persistent dynamic updates, including stale pool/hook identities.
- Add per-operation override, gated by the exact pool/hook permission contract ([DeFi][FIN-19] Authenticated before/after operation hooks and permissions #69); compare quoted and executed fees.
- Implement protocol beneficiary accounting and collection, including capacity and backed-claim interactions.
- Compose fee changes with cross-tick liquidity growth, donations, claim obligations and custom returned deltas ([DeFi][FIN-21] Permissioned extension balance deltas and alternative pricing curves #71).
Attack and comparison matrix
| Case | Expected |
|---|---|
| Dynamic override on fixed-fee pool | Reject |
| Fee update signed by non-owner / stale hook | Reject |
| Excess fee, wrong denominator, negative conversion | Reject or explicit bounded error |
| LP fee diverted into protocol/hook bucket | Reject ownership/liability mismatch |
| Exact-output trade with input exhausted entirely by fee | Defined rejection; never fake output |
| Changed fee after signed user quote | Respect signed max cost/min output; rebuild or reject |
| Repeated collection of already distributed fees | Reject or prove not double counted |
Acceptance artefacts
Keep per-operation balance sheet showing gross input, fee base, LP accrued fees, protocol claim, hook charge, outputs, outstanding liabilities and actual reserve movement. Verify the full transaction at economic roundoff boundaries and quote/settlement parity. Fee control does not authorise withdrawing pool principal.
Security flow
flowchart TD
A["Authenticated pool fee mode"] --> B["Verify update or one-trade override"]
B --> C["Calculate gross trade and fee splits"]
C --> D["LP / protocol / hook entitlements"]
D --> E{"Pool and owner balance sheet closes?"}
E -- No --> X["Reject"]
E -- Yes --> F["Authorised final reserve and fee state"]
Shared assurance rules
- The protocol owns its economic policy; these issues do not add finance-specific syntax or special compiler behaviour. Any missing business-neutral general primitive needs a separate minimal failing case, versioned contract and evidence.
- Freeze concrete source/chain/ABI/asset roles, numerical bounds, revocation semantics and a named reviewer/waiver disposition before claiming acceptance. No original issue or human review is silently inherited.
- Execute complete actual CKB transactions with all required script groups. Preserve independent model, generated builder, checker mutation, exact source/ELF/CellDep/tx/node evidence and worst success/late-rejection budgets. A valid simulator trace, RPC response or indexer record alone is not authority.
Implementation plan
- Freeze immutable static or dynamic fee modes, administrative fee-update authority, per-operation overrides, rounding rules and configured bounds.
- Separate LP accrual, protocol share, extension charges and donor transfers; document application order and legitimate recipients.
- Ensure protocol administrator never gains a general ability to spend liquidity-provider principal or unrelated claim backing.
Executable acceptance
- Stateful fee update and per-trade override produce independently calculated balances and exact-range liquidity fee accrual.
- Wrong authority/recipient, static-pool override, stale fee config, excessive fee, invalid direction and double-charging reject.
- Include zero/max fee, rounding, infeasible exact-output trade with fully consuming fee, and complex hook adjustment cases.
- All LP/protocol/extension amounts and custody reserves balance after full-transaction execution.
Boundary: Dynamic fees and returned balance deltas are different concerns; the latter belongs to FIN-21.
Acceptance policy (all FIN work)
- Status: proposed. Implementer/reviewer unassigned; do not represent an unperformed audit as completed. Freeze versioned API, threat and bounded resource contracts first.
- Core compiler remains protocol-neutral: use ordinary CellScript data types, functions, actions, CKB views and existing generated builders. A demonstrated general-language failure requires its own business-neutral issue.
- All accepted proofs require exact source/compiler/checker/CellDep/transaction identities, independent financial models, hostile full-transaction cases and relevant dev/CI/backend gates. Node/public deployment claims remain separate. No release milestone is inferred.
Verified GitHub dependency links
Core: #64, #66, #69. Downstream: #71 custom accounting, #78 extension corpus.
These are planning links, not executed acceptance or formal GitHub blocking relationships. Parent: #43.
Verified dependencies and implementation sequencing
Hard prerequisites: #64, #66, #69.
Unblocks or integrates with: #71, #78.
Technical dependency note: Fee selection, recipient rights and hook return-delta privileges remain separate claims. Dynamic fee authority is not general reserve spending authority.
This is a documented logical dependency, not a native GitHub blocking relationship or implementation acceptance.
Activity