Skip to content

feat(wrapper): [Math] Rounding error mitigation (#726) - #832

Open
TochukwuJustice wants to merge 2 commits into
BCPathway:mainfrom
TochukwuJustice:math-rounding
Open

feat(wrapper): [Math] Rounding error mitigation (#726)#832
TochukwuJustice wants to merge 2 commits into
BCPathway:mainfrom
TochukwuJustice:math-rounding

Conversation

@TochukwuJustice

Copy link
Copy Markdown

closes #726

Summary of Changes

This PR implements Issue #726: [Math] Rounding error mitigation under the Yield-Bearing Fee Vaults epic:

  • Fixed-Point Math Layer (contracts/wrapper/src/math.rs):
    • Implemented mul_div_down(a, b, d) for overflow-safe floor division $\lfloor \frac{a \times b}{d} \rfloor$.
    • Implemented scale_decimals_down for floor rounding across mismatched decimal precisions.
  • Protocol-Favoring Invariants:
    • Deposits (wrap / convert_to_shares / preview_deposit): Shares are strictly rounded down (floor), preventing share inflation attacks and ensuring depositors never receive unbacked fractional shares.
    • Withdrawals (unwrap / convert_to_assets / preview_withdraw): Underlying assets are strictly rounded down (floor), preventing fractional drainage of vault reserves.
    • Sub-unit Rejection: Operations that round down to 0 output are rejected with WrapperError::InvalidAmount.
  • Public Entry Points: Exposed convert_to_shares, convert_to_assets, preview_deposit, and preview_withdraw on WrapperContract.
  • TypeScript SDK: Added convertToShares(), convertToAssets(), previewDeposit(), and previewWithdraw() to WrapperClient in @bc-forge/sdk.
  • Unit Tests: Added test cases covering fractional truncation on deposit, withdrawal asset flooring, decimal mismatch scaling, and zero-output rejection.

Reason for Changes

In yield-bearing vaults, mathematical rounding must always favor the protocol ("no free money") to maintain pool solvency, protect existing shareholders from share dilution, and prevent attackers from siphoning fractional wei across repeated deposit/withdrawal cycles.

… fee vaults

- Define VaultState struct storing fee rates, limits, exchange rate, and fee accumulation metrics

- Add DataKey::VaultState preserving storage discriminant ordering

- Implement set_vault_state and get_vault_state contract entrypoints with strict invariant validation

- Add emit_vault_state_set contract event

- Add comprehensive unit test suite covering happy paths and error states

- Extend TypeScript SDK WrapperClient with VaultState interface, getter, and setter methods
- Add math module with mul_div_down, mul_div_up, and scale_decimals_down fixed-point arithmetic

- Round shares down on deposit/wrap to prevent unbacked fractional share inflation

- Round underlying tokens down on withdrawal/unwrap to prevent fractional reserve leakage

- Add convert_to_shares, convert_to_assets, preview_deposit, and preview_withdraw contract entrypoints

- Reject sub-unit deposits and withdrawals that round down to zero with InvalidAmount

- Extend TypeScript SDK with conversion and preview methods

- Add comprehensive unit tests covering rounding directions and sub-unit edge cases
@drips-wave

drips-wave Bot commented Aug 26, 2026

Copy link
Copy Markdown

@TochukwuJustice 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! 🚀

Learn more about application limits

@p3ris0n

p3ris0n commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

@TochukwuJustice please fix CI and conflicts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Math] Rounding error mitigation

2 participants