Add withdraw_all convenience function to vault contract - #79
Conversation
📝 WalkthroughWalkthroughAdds ChangesWithdraw All
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@contracts/agent-vault/src/lib.rs`:
- Around line 484-489: Update the insufficient-available branch in withdraw so
the UserAsset storage entry identified by asset_key has its TTL refreshed before
returning VaultError::InsufficientAvailable. Reuse the same TTL-refresh behavior
used by the successful withdrawal path, while preserving the existing balance
validation and error result.
🪄 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 Plus
Run ID: f5d63d9c-dbec-43c2-b8ce-06c85488dcdd
📒 Files selected for processing (2)
contracts/agent-vault/src/lib.rscontracts/agent-vault/src/tests.rs
| let asset_key = DataKey::UserAsset(user.clone(), asset.clone()); | ||
| let account: UserAssetAccount = env.storage().persistent() | ||
| .get(&asset_key).ok_or(VaultError::InsufficientBalance)?; | ||
| let available = account.balance - account.locked; | ||
| if available <= 0 { | ||
| return Err(VaultError::InsufficientAvailable); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Refresh the asset-account TTL before the early error.
When available <= 0, this returns before withdraw refreshes DataKey::UserAsset. Repeated failed withdraw_all calls can therefore leave an otherwise active account to expire.
Proposed fix
let account: UserAssetAccount = env.storage().persistent()
.get(&asset_key).ok_or(VaultError::InsufficientBalance)?;
+ Self::extend_persistent_ttl(&env, &asset_key);
let available = account.balance - account.locked;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let asset_key = DataKey::UserAsset(user.clone(), asset.clone()); | |
| let account: UserAssetAccount = env.storage().persistent() | |
| .get(&asset_key).ok_or(VaultError::InsufficientBalance)?; | |
| let available = account.balance - account.locked; | |
| if available <= 0 { | |
| return Err(VaultError::InsufficientAvailable); | |
| let asset_key = DataKey::UserAsset(user.clone(), asset.clone()); | |
| let account: UserAssetAccount = env.storage().persistent() | |
| .get(&asset_key).ok_or(VaultError::InsufficientBalance)?; | |
| Self::extend_persistent_ttl(&env, &asset_key); | |
| let available = account.balance - account.locked; | |
| if available <= 0 { | |
| return Err(VaultError::InsufficientAvailable); |
🤖 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 `@contracts/agent-vault/src/lib.rs` around lines 484 - 489, Update the
insufficient-available branch in withdraw so the UserAsset storage entry
identified by asset_key has its TTL refreshed before returning
VaultError::InsufficientAvailable. Reuse the same TTL-refresh behavior used by
the successful withdrawal path, while preserving the existing balance validation
and error result.
|
LGTM @mxrtins04 . Just fix the CI fails |
|
@mxrtins04 please fix CI |
closes #67
What changed
Adds
withdraw_all(user, asset)to the vault contract. Computes the withdrawable amount (balance - locked) on-chain and withdraws it in a single call, removing the race where a task completes between an off-chainget_availableread and thewithdrawcall. Reuseswithdrawinternally, so the existinglockedguard,WithdrawEvent, TTL bumps, and logging all apply unchanged.Files added/modified
contracts/agent-vault/src/lib.rs— addedwithdraw_all(env, user, asset)contracts/agent-vault/src/tests.rs— addedtest_withdraw_all_full_withdrawal,test_withdraw_all_with_some_funds_locked,test_withdraw_all_nothing_available_failsSecurity / rollback notes
user.require_auth()before any storage read, same auth boundary aswithdraw.balance - locked; locked funds are left untouched, a subsequent task completion still refunds correctly.InsufficientAvailablewhen nothing is withdrawable (zero balance or fully locked).withdraw's existing logic, event, and TTL handling rather than duplicating it.cargo testpasses.cargo clippy --all-targets -- -D warningsshould be verified before merge (hit a local toolchain issue during implementation, not a code issue).Summary by CodeRabbit