Skip to content

Commit 410099c

Browse files
authored
Merge pull request #675 from ethereum/simpler-code-reading
Reading code plain from a file instead of JSON
2 parents fd0d85d + 734d9e9 commit 410099c

File tree

3 files changed

+20
-24
lines changed

3 files changed

+20
-24
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
generated via iterative calls to the SMT solver for quicker solving
2121
- Aliasing works much better for symbolic and concrete addresses
2222
- Constant propagation for symbolic values
23-
- Allow reading deployedBytecode.object from the forge JSON as --code-file or --code-a-file/--code-b-file
23+
- Allow reading bytecode via --code-file or --code-a-file/--code-b-file. Strips
24+
`\n`, spaces, and ignores leading `0x` to make it easier to use via e.g.
25+
`jq '.deplayedBytecode.object file.json > file.txt'` to parse Forge JSON output
2426
This alleviates the issue when the contract is large and does not fit the command line
2527
limit of 8192 characters
2628
- Two more simplification rules: `ReadByte` & `ReadWord` when the `CopySlice`

cli/cli.hs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ module Main where
99
import Control.Monad (when, forM_, unless)
1010
import Control.Monad.ST (RealWorld, stToIO)
1111
import Control.Monad.IO.Unlift
12+
import Control.Exception (try, IOException)
1213
import Data.ByteString (ByteString)
1314
import qualified Data.ByteString.Lazy as BS
15+
import qualified Data.ByteString.Char8 as BC
1416
import Data.DoubleWord (Word256)
1517
import Data.List (intersperse)
1618
import Data.Maybe (fromMaybe, mapMaybe, fromJust, isNothing, isJust)
@@ -28,9 +30,6 @@ import System.Directory (withCurrentDirectory, getCurrentDirectory, doesDirector
2830
import System.FilePath ((</>))
2931
import System.Exit (exitFailure, exitWith, ExitCode(..))
3032
import Main.Utf8 (withUtf8)
31-
import qualified Data.ByteString.Char8 as BC
32-
import Data.Aeson (decode, (.:))
33-
import Data.Aeson.Types (parseMaybe)
3433

3534
import EVM (initialContract, abstractContract, makeVm)
3635
import EVM.ABI (Sig(..))
@@ -61,7 +60,7 @@ data Command w
6160
= Symbolic -- Symbolically explore an abstract program, or specialized with specified env & calldata
6261
-- vm opts
6362
{ code :: w ::: Maybe ByteString <?> "Program bytecode"
64-
, codeFile :: w ::: Maybe String <?> "Program bytecode from JSON file's deployedBytecode.object field"
63+
, codeFile :: w ::: Maybe String <?> "Program bytecode in a file"
6564
, calldata :: w ::: Maybe ByteString <?> "Tx: calldata"
6665
, address :: w ::: Maybe Addr <?> "Tx: address"
6766
, caller :: w ::: Maybe Addr <?> "Tx: caller"
@@ -112,8 +111,8 @@ data Command w
112111
| Equivalence -- prove equivalence between two programs
113112
{ codeA :: w ::: Maybe ByteString <?> "Bytecode of the first program"
114113
, codeB :: w ::: Maybe ByteString <?> "Bytecode of the second program"
115-
, codeAFile :: w ::: Maybe String <?> "First program's bytecode from JSON file's deployedBytecode.object field"
116-
, codeBFile :: w ::: Maybe String <?> "Second program's bytecode from JSON file's deployedBytecode.object field"
114+
, codeAFile :: w ::: Maybe String <?> "First program's bytecode in a file"
115+
, codeBFile :: w ::: Maybe String <?> "Second program's bytecode in a file"
117116
, sig :: w ::: Maybe Text <?> "Signature of types to decode / encode"
118117
, arg :: w ::: [String] <?> "Values to encode"
119118
, calldata :: w ::: Maybe ByteString <?> "Tx: calldata"
@@ -134,7 +133,7 @@ data Command w
134133
}
135134
| Exec -- Execute a given program with specified env & calldata
136135
{ code :: w ::: Maybe ByteString <?> "Program bytecode"
137-
, codeFile :: w ::: Maybe String <?> "Program bytecode from JSON file's deployedBytecode.object field"
136+
, codeFile :: w ::: Maybe String <?> "Program bytecode in a file"
138137
, calldata :: w ::: Maybe ByteString <?> "Tx: calldata"
139138
, address :: w ::: Maybe Addr <?> "Tx: address"
140139
, caller :: w ::: Maybe Addr <?> "Tx: caller"
@@ -259,21 +258,17 @@ getCode fname code = do
259258
putStrLn "Error: Cannot provide both a file and code"
260259
exitFailure
261260
case fname of
262-
Nothing -> pure code
263-
Just f -> fmap Just $ readJSONcode f
264-
265-
readJSONcode :: FilePath -> IO ByteString
266-
readJSONcode fname = do
267-
contents <- BS.readFile fname
268-
case decode contents of
269-
Nothing -> do
270-
putStrLn "Error: Failed to parse JSON given as code file"
271-
exitFailure
272-
Just json -> case parseMaybe (.: "deployedBytecode") json >>= parseMaybe (.: "object") of
273-
Nothing -> do
274-
putStrLn "Error: Expected a deployedBytecode object in code file"
275-
exitFailure
276-
Just obj -> pure $ BC.pack obj
261+
Nothing -> pure $ fmap strip code
262+
Just f -> do
263+
result <- try (BS.readFile f) :: IO (Either IOException BS.ByteString)
264+
case result of
265+
Left e -> do
266+
putStrLn $ "Error reading file: " <> (show e)
267+
exitFailure
268+
Right content -> do
269+
pure $ Just $ strip (BS.toStrict content)
270+
where
271+
strip = BC.filter (\c -> c /= ' ' && c /= '\n' && c /= '\r' && c /= '\t' && c /= '"')
277272

278273
equivalence :: App m => Command Options.Unwrapped -> m ()
279274
equivalence cmd = do

hevm.cabal

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ executable hevm
213213
witch,
214214
unliftio-core,
215215
with-utf8,
216-
aeson,
217216

218217
--- Test Helpers ---
219218

0 commit comments

Comments
 (0)