Skip to content

Conversation

@msooseth
Copy link
Collaborator

@msooseth msooseth commented Nov 26, 2025

Description

This now finally does what I was aiming for :) You can pass in a function that will be run on the Expr End and the results will be collated. This is now done with the handler.

Notice that we now have to add a task for the Partial as well as the handler needs to be executed on this, here:

-                    -- got us to this point and return a partial leaf for the other side
-                    liftIO . atomically $ writeTChan res (Partial [] (TraceContext (Zipper.toForest vm.traces) vm.env.contracts vm.labels) (MaxIterationsReached vm.state.
pc vm.state.contract))
+                    -- got us to this point and queue a task to return a partial leaf for the other side
+                    let partialLeaf = Partial [] (TraceContext (Zipper.toForest vm.traces) vm.env.contracts vm.labels) (MaxIterationsReached vm.state.pc vm.state.contract
)
+                    liftIO $ atomically $ modifyTVar numTasks (+1)
+                    liftIO $ writeChan taskq $ t { vm = vm, stepper = pure partialLeaf }

This was actually done bye Claude Code at first, but I had to adjust quite a bit.

Now it finds the Cex for prove_inv_identity in src/ABDKMath64x64PropertyTests.sol:CryticABDKMath64x64Properties instantaneously, but keeps running.

I will write a cexHander for equivalence checking as a follow-up PR.

Checklist

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

@msooseth msooseth force-pushed the queue-check branch 3 times, most recently from 496d50b to f6d8375 Compare November 26, 2025 19:51
@msooseth
Copy link
Collaborator Author

Now runs like:

[RUNNING] prove_inv_identity(int128)
   Counterexample:   [validated]
     calldata: prove_inv_identity(-108003701288662363396026832958930103201)
     result:   Revert: 0x4e487b710000000000000000000000000000000000000000000000000000000000000001
   [FAIL] prove_inv_identity
   [WARNING] hevm was only able to partially explore the test prove_inv_identity due to:
      3x -> SMT solver says: Result unknown by SMT solver

This will need an update to the docs. But it should be a lot easier to use for users.

@gustavo-grieco
Copy link
Collaborator

This is great, a leap forward in terms of usability (specially for getting counter examples!)

@msooseth
Copy link
Collaborator Author

Yes, this was the actual goal of the symbolic queue that Martin has helped with a lot. So we are finally making progress to be much more user-friendly, and show relevant results immediately.

@msooseth msooseth force-pushed the queue-check branch 3 times, most recently from 61c2bce to 39f6258 Compare November 26, 2025 20:33
@msooseth msooseth changed the title [DRAFT] Symbolic execution queue should be used to run SMT as well Symbolic execution queue should be used to run SMT as well Nov 26, 2025
@msooseth msooseth marked this pull request as ready for review November 26, 2025 20:36
@msooseth msooseth requested a review from blishko November 26, 2025 20:36
Update ChangeLog

some progress

Making progress

Cleaner

Cleaner

Changelog update

Cleaner

Fixing test.hs

Fix rpc

Cleanup

Cleaner PR

Fixing cexHander to cexHandler

Update name of parameter
@gustavo-grieco
Copy link
Collaborator

Oh, btw, should stop the exploration immediately if a CEX if found?

@msooseth
Copy link
Collaborator Author

msooseth commented Dec 1, 2025

Oh, btw, should stop the exploration immediately if a CEX if found?

Yep, we are thinking about adding that option exactly :) I'll add it in a sec :)

@msooseth msooseth force-pushed the queue-check branch 2 times, most recently from 76ec6be to 749a796 Compare December 2, 2025 13:00
Update

Use Chan

Cleanup
@msooseth
Copy link
Collaborator Author

msooseth commented Dec 2, 2025

Oh, btw, should stop the exploration immediately if a CEX if found?

Yep, we are thinking about adding that option exactly :) I'll add it in a sec :)

OOops, forgot to add that. Will do it tomorrow as a separate PR. Should be very simple :)

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.

I think this looks good! I have just a few small questions.

Comment on lines 847 to 848
putStrLn $ " Exploration finished, " <> show (length results) <> " branch(es) checked in call " <> call <> " of which partial: "
<> show (length smtResults)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this message here is misleading now.
At this point, not only exploration has finished, but also all the solving, no?
At least before, "exploration" meant only the first phase, excluding the solving.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point! I now did this:

commit c5a56bb3ebee5bcf42dc6cf7e1c2bb78c5920e9c (HEAD -> queue-check, origin/queue-check)
Author: Mate Soos <[email protected]>
Date:   Thu Dec 4 12:59:01 2025 +0100

    Better printing to the user

diff --git a/src/EVM/SymExec.hs b/src/EVM/SymExec.hs
index d26971b4..d702c11b 100644
--- a/src/EVM/SymExec.hs
+++ b/src/EVM/SymExec.hs
@@ -820,7 +820,9 @@ verifyInputsWithHandler
 verifyInputsWithHandler solvers opts fetcher preState post cexHandler = do
   conf <- readConfig
   let call = mconcat ["prefix 0x", getCallPrefix preState.state.calldata]
-  when conf.debug $ liftIO $ putStrLn $ "   Exploring call " <> call
+  when conf.debug $ liftIO $ do
+    putStrLn $ "   Keccak preimages in state: " <> (show $ length preState.keccakPreImgs)
+    putStrLn $ "   Exploring call " <> call

   results <- executeVM fetcher opts.iterConf preState $ \leaf -> do
     -- Extract partial if applicable
@@ -846,9 +848,8 @@ verifyInputsWithHandler solvers opts fetcher preState post cexHandler = do
   when conf.debug $ liftIO $ do
     putStrLn $ "   Exploration and solving finished, " <> show (length results) <> " branch(es) checked in call " <> call <> " of which partial: "
                 <> show (length smtResults)
-    putStrLn $ "   Keccak preimages in state: " <> (show $ length preState.keccakPreImgs)
     let cexs = filter (\(res, _) -> not . isQed $ res) smtResults
-    putStrLn $ "   Found " <> show (length cexs) <> " potential counterexample(s) in call " <> call
+    putStrLn $ "   Found " <> show (length cexs) <> " counterexample(s) in call " <> call

   pure (smtResults, catMaybes partials)
   where

So the printing should be better I think!

@msooseth
Copy link
Collaborator Author

msooseth commented Dec 4, 2025

Thanks, you have made this a lot better :) Can you take another look maybe?

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.

This one is ready!

@msooseth msooseth merged commit 137355e into main Dec 4, 2025
6 of 7 checks passed
@msooseth msooseth deleted the queue-check branch December 4, 2025 13:15
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.

4 participants