fix(campaigns): guard withdraw_reserve against non-withdrawn campaigns (#443) - #727
Open
mayborn005 wants to merge 1 commit into
Open
Conversation
withdraw_reserve loaded the campaign and required the creator's auth but never asserted campaign.funds_withdrawn == true. A CampaignReserve is only ever created inside withdraw_funds after funds_withdrawn is set, so a reserve present on a non-withdrawn campaign is an invariant violation (e.g. one seeded via migration or an admin grant) and must not be drainable. Add a defense-in-depth check that returns Error::ValidationFailed when funds_withdrawn is false, plus a regression test that seeds a reserve on a non-withdrawn campaign and asserts the drain is rejected. Fixes Iris-IV#443
|
@mayborn005 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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
withdraw_reserveinsrc/campaigns/withdraw.rsloaded theCampaign, required the creator's auth, and released the reserve — but never assertedcampaign.funds_withdrawn == true.A
CampaignReserveis only ever created insidewithdraw_funds, afterfunds_withdrawnis set totrue. So a reserve present on a non-withdrawn campaign represents an invariant violation (e.g. a reserve seeded through a future migration or an admin grant). Without this guard, such a reserve could be drained.Fix
Add a defense-in-depth check right after the campaign is loaded, mirroring the existing
is_verifiedre-check inwithdraw_funds:Tests
Added
test_withdraw_reserve_rejects_non_withdrawn_campaign, which seeds aCampaignReserve(release window already open) onto a campaign whosefunds_withdrawnis stillfalseand assertswithdraw_reservereturnsError::ValidationFailed.Fixes #443