security: add non_reentrant! RAII macro and enforce CEI on all external calls (Closes #67)#119
Open
neelpote wants to merge 2 commits into
Open
security: add non_reentrant! RAII macro and enforce CEI on all external calls (Closes #67)#119neelpote wants to merge 2 commits into
neelpote wants to merge 2 commits into
Conversation
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.
GrantFox OSS — Official Campaign
Closes #67
Problem
Without a reentrancy guard, any function that makes an external call (token transfer, cross-contract invocation) can be re-entered by a malicious contract before state is written back to storage. The previous implementation used manual
reentrancy::lock/reentrancy::unlockcalls scattered acrossvote— 9 call sites, each a potential leak point if a new early-return is added.lock_tokens,resign_guardian,unlock_tokens, andstart_reward_streamhad no protection at all.What changed
src/reentrancy.rsReentrancyGuard<'a>RAII struct with aDropimpl that callsunlockautomatically on every exit path — normal return, early?, or panic.non_reentrant!macro — one line at the top of any function acquires the lock for its entire scope. No manual unlock ever needed.src/lib.rsreentrancymodulepubso tests and external crates can inspect guard state.reentrancy::lock/reentrancy::unlockcalls invotewithnon_reentrant!(&env).non_reentrant!(&env)tolock_tokens,resign_guardian,unlock_tokens, andstart_reward_stream.src/task.rsnon_reentrant!(env)toregister_tasksandcancel_task.src/drips.rsAllRewardStreamsandRewardStreamstorage writes beforeenv.invoke_contractto enforce CEI.Tests
8 dedicated reentrancy tests in
tests/test.rs:test_strict_reentrancy_guards_prevent_reentry— mock vault re-enters viavote, rejectedtest_reentrancy_lock_tokens_prevented— malicious token re-enterslock_tokens, rejectedtest_reentrancy_resign_guardian_prevented— malicious token re-entersresign_guardian, rejectedtest_reentrancy_unlock_tokens_prevented— malicious token re-entersunlock_tokens, rejectedtest_reentrancy_start_reward_stream_prevented— malicious drips contract re-entersstart_reward_stream, rejectedtest_lock_released_after_successful_vote— lock releases correctly on successtest_lock_released_after_successful_register_task— lock releases correctly on successtest_lock_released_after_failed_vote— lock releases correctly on failureVerification
GrantFox OSS Contribution Guidelines
feat/reentrancy-guards#67cargo fmtandcargo clippyclean