-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CEI pattern static analysis #3168
Conversation
CEI stands for "Checks, Effects, Interactions". We check no storage writes (effects) occur after calling external contracts (interaction). See this [blog post](https://fravoll.github.io/solidity-patterns/checks_effects_interactions.html) for more detail.
An example of a warning issued by the CEI analyzer:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial thoughts! But this looks excellent! Thank you so much 🚀
use sway_ast::Intrinsic::*; | ||
match intr { | ||
StateStoreWord | StateStoreQuad => HashSet::from([Effect::StorageWrite]), | ||
// TODO: figure out the effect of __revert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a revert (or a return) between a contract call and a storage write should not result in a reentrancy warning. That being said, we should probably be warning on dead code in that case anyways?
test/src/e2e_vm_tests/test_programs/should_pass/static_analysis/cei_pattern_violation/Forc.toml
Outdated
Show resolved
Hide resolved
...src/e2e_vm_tests/test_programs/should_pass/static_analysis/cei_pattern_violation/src/main.sw
Show resolved
Hide resolved
...src/e2e_vm_tests/test_programs/should_pass/static_analysis/cei_pattern_violation/src/main.sw
Outdated
Show resolved
Hide resolved
…he context of the cei analysis if there is a statement afterward we should emit a dead code warning
this makes warnings a bit nicer and helps with testing when there is multiple warnings in one contract
I'm very happy with the overall change, thanks! My only nitpick is that the auction test is too large and complex to belong in the E2E test repo. Basically, the test is hard to understand and it is unclear where the violation is. I suggest we go with a much smaller example that showcases the same violation. |
Just realized I need to treat nested code blocks. The fix is on the way |
@mohammadfawaz Pushed an updated, deeper, version of the analysis, please have a look. It still needs a bit more testing, but it already reproduces all the existing tests and I added a very simple test with a nested code block which was not processed previously. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally this looks very reasonable. I'd certainly like to see more testing. At the very least, it would be nice to have full code coverage for cei_pattern_analysis.rs
, but that can be done in a separate PR.
// TODO: jumps are not processed at the moment, so the CEI analysis will work only | ||
// for simple linear assembly blocks, which arguably is the most important use case so far |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jump are not and will porbably never be allowed in asm
blocks, so you're good!
// TODO: jumps are not processed at the moment, so the CEI analysis will work only | |
// for simple linear assembly blocks, which arguably is the most important use case so far | |
No need to worry about jumps because they are not allowed in `asm` blocks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really good to know! I applied the change in a separate commit (added //
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to add a test which uses effects (ref mut
args?) to confirm the left-to-right evaluation of function args and struct initialisers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! The only thing I wonder is if someday down the line we can merge this and other AST-traversing checks we do into one traversal. But the traversals themselves are slightly different so it may not be generalizable (thinking of purity checking mainly).
I'd be okay with that as a follow-up PR since this one has the approvals needed. Your call @anton-trunov |
Actually @anton-trunov mentioned this to me recently when we were chatting. He thinks he has ideas on how to merge purity checking into this as he's already collecting storage access here anyways. |
@anton-trunov I've opened #3342 and assigned it to you so we can follow up with additional testing. |
Awesome! Thanks everyone! |
## Test cases - [x] `if` with interaction in the condition and storage in a branch - [x] `match` with interaction in the condition and storage in branches - [x] Pair or struct with interaction in one component and storage in a subsequent component ### `while`-loops tests - [x] `while` loop with effects in the condition or the body - [x] `while` loop with interaction-then-storage - [x] `while` loop with storage-then-interaction (this is a violation too because on the next loop iteration it will be interaction-then-storage) -- this requires a fix implemented in this PR ### Function application tests - [x] Pure function + argument is a code block with CEI violation - [x] Pure function + first argument does interaction + second argument does storage effect - [x] Storage reading/writing function + argument does interaction - [x] Improved error reporting precision for function application - [x] Left-to-right arguments evaluation Closes #3342
CEI stands for "Checks, Effects, Interactions". We check no storage reads/writes (effects) occur after calling external contracts (interaction). See this blog post and this blogpost for more detail.
TODOs:
__revert
intrinsicstorage.var = ...
asm
blocks directlyStorageAccess
expressionsasm
blocks usingsrw
orsrwq
asm
blocks usingbal
becausebal
actually reads from storageCLI option or attribute to control the warnings(an internal discussion showed that we cannot do this at the moment, I guess this should be handled as a separate issue)close #10