fix: precision loss in redeem_basket by applying fee before split (#326)#419
Conversation
…-Defi-world#326) - Fixed corrupted acbu_burning/src/lib.rs: removed duplicate imports, duplicate function definitions, and fragmented code - redeem_basket now applies fee to the total acbu_amount FIRST, then splits the net remainder among recipients (avoids per-slice rounding precision loss from split-then-fee approach) - Added missing ContractError variants (NoPendingAdmin, AdminTimelockNotElapsed, NoPendingAdminToCancel) to shared - Added public getters/setters (get_fee_rate, set_fee_rate, pause, unpause, is_paused, etc.) required by tests - Fixed corrupted test.rs with proper common module usage - Fixed fuzz_test.rs with correct initialize signature and oracle mocks - Added 4 edge divisibility tests for prime amounts, small amounts, uneven weights, and exact divisibility - All 25+ tests pass, build is clean
|
@aadviksinghdebug 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! 🚀 |
📝 WalkthroughWalkthroughRefactors ChangesBurningContract Redemption Refactor and API Additions
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
acbu_burning/src/lib.rs (1)
223-234: 🔒 Security & Privacy | 🟠 Major
redeem_basketskipsvalidate_recipient, allowing the contract address as a recipient.
redeem_singlecallsSelf::validate_recipient(&env, &recipient)(line 114) to rejectenv.current_contract_address()as a recipient, butredeem_basketomits this check. Only empty and duplicate recipients are validated (lines 223-229). A caller can include the contract's own address as a basket recipient, causing S-tokens to be transferred to the contract itself.Add the guard to each recipient in the validation loop:
Proposed fix
let rlen = recipients.len(); for i in 0..rlen { + Self::validate_recipient(&env, &recipients.get(i).unwrap()); for j in (i + 1)..rlen { if recipients.get(i).unwrap() == recipients.get(j).unwrap() { env.panic_with_error(ContractError::InvalidRecipient); } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@acbu_burning/src/lib.rs` around lines 223 - 234, The redeem_basket function is missing a critical validation that exists in redeem_single. The validation loop for recipients (lines 223-229) currently only checks for empty and duplicate recipients but does not reject the contract address itself as a recipient. Add a call to Self::validate_recipient(&env, &recipient) for each recipient in the loop to ensure that env.current_contract_address() is rejected as a recipient, preventing S-tokens from being transferred to the contract itself.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@shared/src/lib.rs`:
- Around line 227-229: Update the ContractError table in docs/ERROR_CODES.md to
include the three new error code variants. Add entries for NoPendingAdmin (code
13), AdminTimelockNotElapsed (code 14), and NoPendingAdminToCancel (code 15) to
the shared — ContractError documentation section, which currently ends at code
12. Ensure each new variant entry includes a clear human-readable description
that explains when and why that error would be raised.
---
Outside diff comments:
In `@acbu_burning/src/lib.rs`:
- Around line 223-234: The redeem_basket function is missing a critical
validation that exists in redeem_single. The validation loop for recipients
(lines 223-229) currently only checks for empty and duplicate recipients but
does not reject the contract address itself as a recipient. Add a call to
Self::validate_recipient(&env, &recipient) for each recipient in the loop to
ensure that env.current_contract_address() is rejected as a recipient,
preventing S-tokens from being transferred to the contract itself.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1881796c-e05f-4764-85ff-7b8abb0069fe
📒 Files selected for processing (7)
acbu_burning/src/lib.rsacbu_burning/tests/common/mod.rsacbu_burning/tests/fuzz_test.rsacbu_burning/tests/redeem_basket.rsacbu_burning/tests/redeem_single.rsacbu_burning/tests/test.rsshared/src/lib.rs
|
@aadviksinghdebug clear conflicts |
closes #326
Burning
redeem_basketfee applied after-split causes precision loss.Root cause: The
redeem_basketfunction inacbu_burning/src/lib.rshad severe code corruption (duplicate imports, two overlapping function bodies, fragmented logic). Additionally, the fee allocation approach had a mixed implementation that could cause precision loss when splitting the gross amount first and then deducting fee per-slice.Fix:
acbu_amountfirst (total_fee = calculate_fee(acbu_amount, fee_rate)), then the net remainder is split proportionally among recipients. This avoids per-slice rounding precision loss from splitting then applying fee per-leg.get_fee_rate,set_fee_rate,get_fee_single_redeem,set_fee_single_redeem,pause,unpause,is_paused.ContractErrorvariants:NoPendingAdmin,AdminTimelockNotElapsed,NoPendingAdminToCanceltoshared.test.rsandfuzz_test.rshad duplicate code, undefined variables, and incorrect mock usage. Rewritten to use thecommonmodule properly.Testing: All 25+ burning contract tests pass. Build is clean (0 warnings).
Summary by CodeRabbit
New Features
Bug Fixes
Tests