Skip to content

Commit 4b2a581

Browse files
authored
Merge pull request #199 from ethereum/bump-hevm
Bump hevm
2 parents 1476033 + fe85713 commit 4b2a581

File tree

6 files changed

+52
-42
lines changed

6 files changed

+52
-42
lines changed

flake.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Act/CLI.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ decompile' :: FilePath -> Text -> Solvers.Solver -> Maybe Integer -> Bool -> IO
222222
decompile' solFile' cid solver' timeout debug' = do
223223
let config = if debug' then debugActConfig else defaultActConfig
224224
cores <- fmap fromIntegral getNumProcessors
225-
json <- solc Solidity =<< TIO.readFile solFile'
225+
json <- flip (solc Solidity) False =<< TIO.readFile solFile'
226226
let (Contracts contracts, _, _) = fromJust $ readStdJSON json
227227
case Map.lookup ("hevm.sol:" <> cid) contracts of
228228
Nothing -> do
@@ -274,7 +274,7 @@ hevm actspec sol' code' initcode' solver' timeout debug' = do
274274

275275
bytecodes :: Text -> Text -> IO (BS.ByteString, BS.ByteString)
276276
bytecodes cid src = do
277-
json <- solc Solidity src
277+
json <- solc Solidity src False
278278
let (Contracts sol', _, _) = fromJust $ readStdJSON json
279279
let err = error $ "Cannot find Solidity contract " <> Text.unpack cid
280280
pure ((fromMaybe err . Map.lookup ("hevm.sol" <> ":" <> cid) $ sol').creationCode,

src/Act/Decompile.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ import EVM.Solidity hiding (SlotType(..))
4646
import EVM.Solidity qualified as EVM (SlotType(..))
4747
import EVM.Types qualified as EVM
4848
import EVM.Types ((.<=), (.>=), (.==))
49-
import EVM.Solvers (SolverGroup, checkSat, CheckSatResult(..))
50-
import EVM.SymExec hiding (EquivResult)
49+
import EVM.Solvers (SolverGroup, checkSat)
50+
import EVM.SymExec
5151
import EVM.Expr qualified as Expr
5252
import EVM.Traversals (mapExprM)
5353
import GHC.IO hiding (liftIO)
@@ -111,7 +111,7 @@ summarize solvers contract = do
111111
let fragments = fmap (uncurry symAbiArg) contract.constructorInputs
112112
args = combineFragments' fragments 0 (EVM.ConcreteBuf "")
113113
initVM <- liftIO $ stToIO $ abstractVM (fst args, []) contract.creationCode Nothing True
114-
expr <- Expr.simplify <$> interpret (Fetch.oracle solvers Nothing) Nothing 1 StackBased initVM runExpr
114+
expr <- Expr.simplify <$> interpret (Fetch.oracle solvers Nothing) iterConfig initVM runExpr
115115
let branches = flattenExpr expr
116116
if any isPartial branches
117117
then pure . Left $ "partially explored branches in creation code:\n" <> T.unlines (fmap formatExpr (filter isPartial branches))
@@ -126,7 +126,7 @@ summarize solvers contract = do
126126
. (flip combineFragments) (EVM.AbstractBuf "txdata")
127127
$ fmap (uncurry symAbiArg) method.inputs
128128
prestate <- liftIO $ stToIO $ abstractVM (fst calldata, []) contract.runtimeCode Nothing False
129-
expr <- Expr.simplify <$> interpret (Fetch.oracle solvers Nothing) Nothing 1 StackBased prestate runExpr
129+
expr <- Expr.simplify <$> interpret (Fetch.oracle solvers Nothing) iterConfig prestate runExpr
130130
let branches = flattenExpr expr
131131
if any isPartial branches
132132
then pure . Left $ "partially explored branches in runtime code:\n" <> T.unlines (fmap formatExpr (filter isPartial branches))
@@ -168,8 +168,8 @@ makeIntSafe solvers expr = evalStateT (mapExprM go expr) mempty
168168
, fromMaybe (EVM.PBool True) (Map.lookup r s)
169169
, EVM.PNeg safe
170170
]
171-
liftIO (checkSat solvers (assertProps defaultActConfig ps)) >>= \case
172-
Unsat -> do
171+
liftIO (checkSat solvers Nothing (assertProps defaultActConfig ps)) >>= \case
172+
EVM.Qed -> do
173173
put $ Map.insert full safe s
174174
pure full
175175
_ -> pure $ EVM.Mod full (EVM.Lit MAX_UINT)

src/Act/HEVM.hs

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ import EVM.ABI (Sig(..))
4949
import qualified EVM hiding (bytecode)
5050
import qualified EVM.Types as EVM hiding (FrameState(..))
5151
import EVM.Expr hiding (op2, inRange, div, xor, readStorage)
52-
import EVM.SymExec hiding (EquivResult, isPartial, reachable)
53-
import qualified EVM.SymExec as SymExec (EquivResult, ProofResult(..))
54-
import EVM.SMT (SMTCex(..), assertProps)
52+
import EVM.SymExec hiding (isPartial, reachable)
53+
import EVM.SMT (assertProps)
5554
import EVM.Solvers
5655
import EVM.Effects
5756
import EVM.Format as Format
@@ -73,7 +72,7 @@ type ContractMap = M.Map (EVM.Expr EVM.EAddr) (EVM.Expr EVM.EContract, Id)
7372
-- when we encounter a constructor call.
7473
type CodeMap = M.Map Id (Contract, BS.ByteString, BS.ByteString)
7574

76-
type EquivResult = ProofResult () (T.Text, SMTCex) T.Text T.Text
75+
type EquivResult = EVM.ProofResult (String, EVM.SMTCex) String
7776

7877
initAddr :: EVM.Expr EVM.EAddr
7978
initAddr = EVM.SymAddr "entrypoint"
@@ -677,14 +676,14 @@ checkOp (Create _ _ _) = error "Internal error: invalid in range expression"
677676
-- | Wrapper for the equivalenceCheck function of hevm
678677
checkEquiv :: App m => SolverGroup -> [EVM.Expr EVM.End] -> [EVM.Expr EVM.End] -> m [EquivResult]
679678
checkEquiv solvers l1 l2 = do
680-
(res, _) <- equivalenceCheck' solvers l1 l2 False
681-
pure $ fmap toEquivRes res
679+
EqIssues res _ <- equivalenceCheck' solvers l1 l2 False
680+
pure $ fmap (toEquivRes . fst) res
682681
where
683-
toEquivRes :: SymExec.EquivResult -> EquivResult
684-
toEquivRes (Cex cex) = Cex ("\x1b[1mThe following input results in different behaviours\x1b[m", cex)
685-
toEquivRes (Qed a) = Qed a
686-
toEquivRes (SymExec.Unknown ()) = SymExec.Unknown ""
687-
toEquivRes (SymExec.Error b) = SymExec.Error (T.pack b)
682+
toEquivRes :: EVM.EquivResult -> EquivResult
683+
toEquivRes (EVM.Cex cex) = EVM.Cex ("\x1b[1mThe following input results in different behaviours\x1b[m", cex)
684+
toEquivRes EVM.Qed = EVM.Qed
685+
toEquivRes (EVM.Unknown s) = EVM.Unknown s
686+
toEquivRes (EVM.Error b) = EVM.Error b
688687

689688

690689
-- | Create the initial contract state before analysing a contract
@@ -738,7 +737,7 @@ getInitContractState solvers iface pointers preconds cmap = do
738737
checkQueries :: App m => [EVM.Prop] -> m (Error String ())
739738
checkQueries queries = do
740739
conf <- readConfig
741-
res <- liftIO $ checkSat solvers (assertProps conf queries)
740+
res <- liftIO $ checkSat solvers Nothing (assertProps conf queries)
742741
checkResult (makeCalldata iface) Nothing [toVRes msg res]
743742

744743
makeSymAddr n = EVM.WAddr (EVM.SymAddr $ "freshSymAddr" <> (T.pack $ show n))
@@ -955,15 +954,15 @@ checkInputSpaces solvers l1 l2 = do
955954
let queries = fmap (assertProps conf) [ [ EVM.PNeg (EVM.por p1), EVM.por p2 ]
956955
, [ EVM.por p1, EVM.PNeg (EVM.por p2) ] ]
957956

958-
results <- liftIO $ mapConcurrently (checkSat solvers) queries
957+
results <- liftIO $ mapConcurrently (checkSat solvers Nothing) queries
959958
let results' = case results of
960959
[r1, r2] -> [ toVRes "\x1b[1mThe following inputs are accepted by Act but not EVM\x1b[m" r1
961960
, toVRes "\x1b[1mThe following inputs are accepted by EVM but not Act\x1b[m" r2 ]
962961
_ -> error "Internal error: impossible"
963962

964-
case all isQed results' of
965-
True -> pure [Qed ()]
966-
False -> pure $ filter (/= Qed ()) results'
963+
case all EVM.isQed results' of
964+
True -> pure [EVM.Qed]
965+
False -> pure $ filter (/= EVM.Qed) results'
967966

968967

969968

@@ -978,7 +977,7 @@ checkAbi solver contract cmap = do
978977
evmBehvs <- getRuntimeBranches solver hevmstorage (txdata, []) 0 -- TODO what freshAddr goes here?
979978
conf <- readConfig
980979
let queries = fmap (assertProps conf) $ filter (/= []) $ fmap (checkBehv selectorProps) evmBehvs
981-
res <- liftIO $ mapConcurrently (checkSat solver) queries
980+
res <- liftIO $ mapConcurrently (checkSat solver Nothing) queries
982981
checkResult (txdata, []) Nothing (fmap (toVRes msg) res)
983982

984983
where
@@ -1034,19 +1033,19 @@ assertSelector txdata sig =
10341033

10351034
-- * Utils
10361035

1037-
toVRes :: T.Text -> CheckSatResult -> EquivResult
1036+
toVRes :: String -> EVM.SMTResult -> EquivResult
10381037
toVRes msg res = case res of
1039-
Sat cex -> Cex (msg, cex)
1040-
EVM.Solvers.Unknown e -> SymExec.Unknown (T.pack e)
1041-
Unsat -> Qed ()
1042-
EVM.Solvers.Error e -> SymExec.Error (T.pack e)
1038+
EVM.Cex cex -> EVM.Cex (msg, cex)
1039+
EVM.Unknown e -> EVM.Unknown e
1040+
EVM.Qed -> EVM.Qed
1041+
EVM.Error e -> EVM.Error e
10431042

10441043

10451044
checkResult :: App m => Calldata -> Maybe Sig -> [EquivResult] -> m (Error String ())
10461045
checkResult calldata sig res =
1047-
case any isCex res of
1046+
case any EVM.isCex res of
10481047
False ->
1049-
case any isUnknown res || any isError res of
1048+
case any EVM.isUnknown res || any EVM.isError res of
10501049
True -> do
10511050
showMsg "\x1b[41mNo discrepancies found but timeouts or solver errors were encountered. \x1b[m"
10521051
pure $ Failure $ NE.singleton (nowhere, "Failure: Cannot prove equivalence.")
@@ -1055,7 +1054,7 @@ checkResult calldata sig res =
10551054
pure $ Success ()
10561055
True -> do
10571056
let cexs = mapMaybe getCex res
1058-
showMsg $ T.unpack . T.unlines $ [ "\x1b[41mNot equivalent.\x1b[m", "" , "-----", ""] <> (intersperse (T.unlines [ "", "-----" ]) $ fmap (\(msg, cex) -> msg <> "\n" <> formatCex (fst calldata) sig cex) cexs)
1057+
showMsg $ T.unpack . T.unlines $ [ "\x1b[41mNot equivalent.\x1b[m", "" , "-----", ""] <> (intersperse (T.unlines [ "", "-----" ]) $ fmap (\(msg, cex) -> T.pack msg <> "\n" <> formatCex (fst calldata) sig cex) cexs)
10591058
pure $ Failure $ NE.singleton (nowhere, "Failure: Cannot prove equivalence.")
10601059

10611060
-- | Pretty prints a list of hevm behaviours for debugging purposes

src/Act/HEVM_utils.hs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import Act.Syntax.Untyped (makeIface)
2626
import qualified EVM.Types as EVM
2727
import EVM.Types (VM(..))
2828
import EVM.Expr hiding (op2, inRange)
29-
import EVM.SymExec hiding (EquivResult, isPartial, abstractVM, loadSymVM)
29+
import EVM.SymExec hiding (isPartial, abstractVM, loadSymVM)
3030
import EVM.Solvers
3131
import qualified EVM.Format as Format
3232
import qualified EVM.Fetch as Fetch
@@ -53,12 +53,15 @@ defaultActConfig = Config
5353
, numCexFuzz = 0
5454
, onlyCexFuzz = False
5555
, decomposeStorage = False
56-
, maxBranch = 100
5756
, promiseNoReent = False
5857
, maxBufSize = 64
58+
, maxWidth = 100
59+
, maxDepth = Nothing
5960
, verb = 0
61+
, simp = True
6062
}
6163

64+
6265
debugActConfig :: Config
6366
debugActConfig = defaultActConfig { dumpQueries = True, dumpExprs = True, dumpEndStates = True, debug = True }
6467

@@ -107,11 +110,19 @@ checkPartial nodes =
107110
showMsg ""
108111
showMsg . T.unpack . T.unlines . fmap (Format.indent 2 . ("- " <>)) . fmap Format.formatPartial . nubOrd $ (getPartials nodes)
109112

113+
114+
iterConfig :: IterConfig
115+
iterConfig = IterConfig
116+
{ maxIter = Nothing
117+
, askSmtIters = 1
118+
, loopHeuristic = StackBased
119+
}
120+
110121
-- | decompiles the given EVM bytecode into a list of Expr branches
111122
getRuntimeBranches :: App m => SolverGroup -> [(EVM.Expr EVM.EAddr, EVM.Contract)] -> Calldata -> Int -> m [EVM.Expr EVM.End]
112123
getRuntimeBranches solvers contracts calldata fresh = do
113124
prestate <- liftIO $ stToIO $ abstractVM contracts calldata fresh
114-
expr <- interpret (Fetch.oracle solvers Nothing) Nothing 1 StackBased prestate runExpr
125+
expr <- interpret (Fetch.oracle solvers Nothing) iterConfig prestate runExpr
115126
let simpl = simplify expr
116127
let nodes = flattenExpr simpl
117128
checkPartial nodes
@@ -122,7 +133,7 @@ getRuntimeBranches solvers contracts calldata fresh = do
122133
getInitcodeBranches :: App m => SolverGroup -> BS.ByteString -> [(EVM.Expr EVM.EAddr, EVM.Contract)] -> Calldata -> [EVM.Prop] -> Int -> m [EVM.Expr EVM.End]
123134
getInitcodeBranches solvers initcode contracts calldata precond fresh = do
124135
initVM <- liftIO $ stToIO $ abstractInitVM initcode contracts calldata precond fresh
125-
expr <- interpret (Fetch.oracle solvers Nothing) Nothing 1 StackBased initVM runExpr
136+
expr <- interpret (Fetch.oracle solvers Nothing) iterConfig initVM runExpr
126137
let simpl = simplify expr
127138
let nodes = flattenExpr simpl
128139
checkPartial nodes
@@ -170,7 +181,7 @@ loadSymVM (entryaddr, entrycontract) othercontracts callvalue cd create fresh =
170181
, origin = EVM.SymAddr "origin"
171182
, gas = ()
172183
, gaslimit = 0xffffffffffffffff
173-
, number = 0
184+
, number = EVM.Lit 0
174185
, timestamp = EVM.Lit 0
175186
, coinbase = EVM.SymAddr "coinbase"
176187
, prevRandao = 42069

src/Test/Decompile.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ decompilerTests = testGroup "decompiler"
106106

107107
checkDecompilation :: Text -> Text -> Assertion
108108
checkDecompilation contract src = do
109-
json <- solc Solidity src
109+
json <- solc Solidity src False
110110
let (Contracts sol, _, _) = fromJust $ readStdJSON json
111111
let c = fromJust $ Map.lookup ("hevm.sol:" <> contract) sol
112112
runEnv (Env defaultActConfig) (Solvers.withSolvers CVC5 1 1 (Just 100000000) (decompile c)) >>= \case

0 commit comments

Comments
 (0)