Contract: Re-entrancy guard analysis#742
Open
wheval wants to merge 1 commit into
Open
Conversation
docs/security/REENTRANCY_ANALYSIS.md analyzes execute()/execute_internal for re-entrancy: the state update happens after the cross-contract call (not checks-effects-interactions ordered), so the global enter_security_guard mutex is load-bearing, not redundant - confirmed necessary and sufficient. While tracing every guarded call path, found that execute_internal calls the *guarded* public execute_yield_strategy() for any task with a yield_strategy configured, which re-enters enter_security_guard while execute()'s own guard is still held and panics unconditionally - so any task with a yield_strategy could never execute. This had no test coverage. Fixes it the same way execute()/execute_internal are already split: extracted execute_yield_strategy_internal (guard-free), with the public execute_yield_strategy still guarding itself as a standalone entry point, and execute_internal now calling the internal helper directly. Adds a regression test exercising a yield-strategy task through the public execute() entry point end-to-end, including the real keeper fee payment. Closes SoroLabs#699
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
docs/security/REENTRANCY_ANALYSIS.md: analyzesexecute()/execute_internalfor re-entrancy risk against arbitrarytarget/protocol_addresscontracts. Finds the code is not checks-effects-interactions ordered (the cross-contract call happens before thelast_runstate update), so the existingenter_security_guard/exit_security_guardglobal mutex is load-bearing, not redundant - confirmed necessary and sufficient rather than reordering writes.execute_internal's yield-strategy branch called the guarded publicexecute_yield_strategy()for any task with ayield_strategyconfigured. Sinceexecute()already holds the lock at that point, this immediately re-enteredenter_security_guardand panicked - meaning any task with ayield_strategyset could never execute successfully, and this had zero test coverage (no existing test ever registered a task withyield_strategy: Some(_)and calledexecute()).execute/execute_internalare already split: extracted a guard-freeexecute_yield_strategy_internal; the publicexecute_yield_strategystill guards itself as a standalone entry point,execute_internalnow calls the internal helper directly so it sharesexecute()'s existing lock instead of trying to acquire a second one.test_execute_with_yield_strategy_does_not_trip_reentrancy_guard, exercising a yield-strategy task through the publicexecute()entry point end-to-end (real token, real keeper fee payment) - fails before the fix, passes after.Closes #699
Test plan
cargo test --libincontract/- all 136 tests pass, including the new regression test