Skip to content

Conversation

msooseth
Copy link
Collaborator

@msooseth msooseth commented Dec 18, 2024

Description

Overapproximate returned state when we can't figure out STATICCALL callee. In this case, set returndata and the top of the stack to a symbolic value. Note that there are two cases we need to do fallback actions. Once when the address can't be forced into a (potentially symbolic) address, which is the "trivial" Nothing case. However, when it can be forced, and the symbolic address is present in the env.contracts, we should resolve and use it. Otherwise, we should fallback. So there are in fact two cases we should call fallback. Hence, I created a function to check if the address can be resolved, and check inside Nothing.

I also fixed a test and added tests specific for this use-case.

Checklist

  • tested locally
  • added automated tests
  • updated the docs
  • updated the changelog

@msooseth msooseth force-pushed the overapproximate-staticcall branch 2 times, most recently from 76d8ff2 to b34f4f8 Compare December 19, 2024 16:53
@msooseth msooseth changed the title [DRAFT] Overapproximate staticcall in case we can't resolve callee Overapproximate staticcall in case we can't resolve callee Dec 19, 2024
@msooseth msooseth marked this pull request as ready for review December 19, 2024 17:11
@msooseth msooseth requested review from blishko and arcz December 19, 2024 17:11
src/EVM.hs Outdated
-- overaapproximate by returning a symbolic value
freshVar <- use #freshVar
assign #freshVar (freshVar + 1)
pushSym (Var ("staticcall-result-stack-" <> (pack . show) freshVar))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this symbol is the 0 or 1 returned by the staticcall right? Would it be useful to constraint it to those values?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OH WOW, yes! Ill do it in the next 2h!

Copy link
Collaborator Author

@msooseth msooseth Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really-really cool find! I now added a constraint, and I also added a testcase, using YUL, to check that the return value is indeed constrained to 0/1:

   uint success;
   assemby {
    ...
              success := staticcall(
                  gas(),          // Forward all available gas
                  inputAddr,      // Address to call
                  callData,       // Input data location
                  68,             // Input data size (4 bytes for function signature + 32 bytes each for x and y)
                  0,              // Output data location (0 means we don't care about the output)
                  0               // Output data size
              )
   }
   assert(success <= 1);

This yul code is the only way to actually check that the returned value is constrained -- Solidity only allows you to assign the return value to a bool, and so it can't be checked (AFAIK?). Without the constraint, the above actually could fail. With the constraint, the above always succeeds -- since success cannot be larger than 1. So the constraint is there, and is effective, as checked by this test case.

Thanks for this!!

msooseth and others added 7 commits January 6, 2025 15:45
Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com>
Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com>
It can only be 0/1, as spotted by @elopez. Thanks!

Also adding a test case that specifically checks for this
@@ -2060,10 +2060,197 @@ tests = testGroup "hevm"
}
}
|]
let sig = Just (Sig "checkval(uint256,uint256)" [AbiUIntType 256, AbiUIntType 256])
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was actually an incorrect test case. Fixed.

@msooseth msooseth requested a review from elopez January 8, 2025 16:03
Copy link
Collaborator

@blishko blishko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@msooseth msooseth merged commit 828edc1 into main Jan 9, 2025
9 checks passed
@blishko blishko deleted the overapproximate-staticcall branch July 29, 2025 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants