Skip to content
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

Cheatcodes as per new std-forge library #567

Merged
merged 29 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a16d3c0
Making assert... into reverts, as per std-forge
msooseth Oct 24, 2024
29279b0
Fixing some issues with tests
msooseth Oct 29, 2024
2cb92a9
Temporary
msooseth Oct 30, 2024
92a7048
Making progress
msooseth Oct 31, 2024
0905738
Moving to forge-std
msooseth Oct 31, 2024
da695e3
Fixing up
msooseth Oct 31, 2024
fed5b2a
Better error reporting
msooseth Oct 31, 2024
b00abc9
Update to bubble hevm errors back up
msooseth Nov 8, 2024
0f7eb14
Temporarily ignoring test while we figure out what to do with it
msooseth Nov 25, 2024
ad1e91a
Fixing interpretFailure
msooseth Nov 25, 2024
e155fb7
Ripping out interpretFailure idea
msooseth Nov 25, 2024
c8bd6b7
More debug printing, enabling tests
msooseth Nov 25, 2024
ed08948
Adding notes
msooseth Nov 25, 2024
3797dc0
Much easier to review and more compact thanks to @d-xo
msooseth Nov 26, 2024
65a8103
One more test on mem pairs
msooseth Nov 26, 2024
a6124bb
Fixing up call signature generation
msooseth Nov 26, 2024
a6151dd
Removing warnings
msooseth Nov 26, 2024
753a8f0
Fixing up rpc tests
msooseth Nov 26, 2024
66dbc56
Updating changelog
msooseth Nov 26, 2024
a01a83e
Removing DSTest, replacing with forge-std
msooseth Nov 26, 2024
dab414a
Update changelog
msooseth Nov 26, 2024
a4c6a95
Cleanup of changelog
msooseth Nov 27, 2024
1d55496
This is not needed anymore, it's not encoded there
msooseth Nov 27, 2024
4de8f70
Removing space
msooseth Nov 27, 2024
be2a67c
Merge branch 'main' into implement_new_cheatcodes
msooseth Nov 29, 2024
88ccb41
Allowing backwards compatibility with ds-test
msooseth Dec 2, 2024
8e4dce0
Merge branch 'main' into implement_new_cheatcodes
msooseth Dec 2, 2024
0d07497
Separate option for DSTest-type assertion type
msooseth Dec 2, 2024
f7219b9
Updating changelog
msooseth Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- More complete and precise array/mapping slot rewrite, along with a copySlice improvement
- Use a let expression in copySlice to decrease expression size
- The `--debug` flag now dumps the internal expressions as well
- hevm now uses the std-forge library's way of detecting failures, i.e. through
reverting with a specific error code

## Added
- More POr and PAnd rules
Expand Down
101 changes: 101 additions & 0 deletions src/EVM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import Data.Bits (FiniteBits, countLeadingZeros, finiteBitSize)
import Data.ByteArray qualified as BA
import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.ByteString.Char8 qualified as BS8
import Data.ByteString.Base16 qualified as BS16
import Data.ByteString.Lazy (fromStrict)
import Data.ByteString.Lazy qualified as LS
Expand Down Expand Up @@ -1903,6 +1904,57 @@ cheatActions = Map.fromList
, $(envReadMultipleCheat "envBytes32(string,string)" $ AbiBytesType 32) stringToBytes32
, $(envReadMultipleCheat "envString(string,string)" AbiStringType) stringToByteString
, $(envReadMultipleCheat "envBytes(bytes,bytes)" AbiBytesDynamicType) stringHexToByteString
, action "asserTrue(bool)" $ \sig input ->
case decodeBuf [AbiBoolType] input of
CAbi [AbiBool True] -> doStop
CAbi [AbiBool False] -> frameRevert "assertion failed"
_ -> vmError $ BadCheatCode ("assertTrue(bool) parameter decoding failed") sig
, action "asserFalse(bool)" $ \sig input ->
case decodeBuf [AbiBoolType] input of
CAbi [AbiBool False] -> doStop
CAbi [AbiBool True] -> frameRevert "assertion failed"
_ -> vmError $ BadCheatCode ("assertFalse(bool) parameter decoding failed") sig
, action "assertEq(bool,bool)" $ assertEq AbiBoolType
, action "assertEq(uint256,uint256)" $ assertEq (AbiUIntType 256)
, action "assertEq(int256,int256)" $ assertEq (AbiIntType 256)
, action "assertEq(address,address)" $ assertEq AbiAddressType
, action "assertEq(bytes32,bytes32)" $ assertEq (AbiBytesType 32)
, action "assertEq(string,string)" $ assertEq AbiStringType
--
, action "assertNotEq(bytes,bytes)" $ assertNotEq (AbiBytesDynamicType)
, action "assertNotEq(bool,bool)" $ assertNotEq AbiBoolType
, action "assertNotEq(uint256,uint256)" $ assertNotEq (AbiUIntType 256)
, action "assertNotEq(int256,int256)" $ assertNotEq (AbiIntType 256)
, action "assertNotEq(address,address)" $ assertNotEq AbiAddressType
, action "assertNotEq(bytes32,bytes32)" $ assertNotEq (AbiBytesType 32)
, action "assertNotEq(string,string)" $ assertNotEq AbiStringType
, action "assertNotEq(bytes,bytes)" $ assertNotEq (AbiBytesDynamicType)
--
, action "assertNotEqMsg(bytes,bytes)" $ assertNotEqMsg (AbiBytesDynamicType)
, action "assertNotEqMsg(bool,bool)" $ assertNotEqMsg AbiBoolType
, action "assertNotEqMsg(uint256,uint256)" $ assertNotEqMsg (AbiUIntType 256)
, action "assertNotEqMsg(int256,int256)" $ assertNotEqMsg (AbiIntType 256)
, action "assertNotEqMsg(address,address)" $ assertNotEqMsg AbiAddressType
, action "assertNotEqMsg(bytes32,bytes32)" $ assertNotEqMsg (AbiBytesType 32)
, action "assertNotEqMsg(string,string)" $ assertNotEqMsg AbiStringType
, action "assertNotEqMsg(bytes,bytes)" $ assertNotEqMsg (AbiBytesDynamicType)
--
, action "assertEq(bool,bool,string)" $ assertEqMsg AbiBoolType
, action "assertEq(uint256,uint256,string)" $ assertEqMsg (AbiUIntType 256)
, action "assertEq(int256,int256,string)" $ assertEqMsg (AbiIntType 256)
, action "assertEq(address,address,string)" $ assertEqMsg AbiAddressType
, action "assertEq(bytes32,bytes32,string)" $ assertEqMsg (AbiBytesType 32)
, action "assertEq(string,string,string)" $ assertEqMsg AbiStringType
, action "assertEq(bytes,bytes,string)" $ assertEqMsg (AbiBytesDynamicType)
--
, action "assertLt(uint256,uint256)" $ assertLt (AbiUIntType 256)
, action "assertLt(int256,int256)" $ assertLt (AbiIntType 256)
, action "assertLe(uint256,uint256)" $ assertLe (AbiUIntType 256)
, action "assertLe(int256,int256)" $ assertLe (AbiIntType 256)
, action "assertGt(uint256,uint256)" $ assertGt (AbiUIntType 256)
, action "assertGt(int256,int256)" $ assertGt (AbiIntType 256)
, action "assertGe(uint256,uint256)" $ assertGe (AbiUIntType 256)
, action "assertGe(int256,int256)" $ assertGe (AbiIntType 256)
]
where
action s f = (abiKeccak s, f (abiKeccak s))
Expand Down Expand Up @@ -1942,6 +1994,55 @@ cheatActions = Map.fromList
stringToByteString = Right . Char8.pack
stringHexToByteString :: String -> Either ByteString ByteString
stringHexToByteString s = either (const $ Left "invalid bytes value") Right $ BS16.decodeBase16Untyped . Char8.pack . strip0x $ s
paramDecodeErr abitype name = name <> "(" <> (show abitype) <> "," <> (show abitype) <>
") parameter decoding failed"
paramDecodeMsgErr abitype name = name <> "(" <> (show abitype) <> "," <> (show abitype) <>
",string) parameter decoding failed"
revertErr a b comp = frameRevert $ "assertion failed: " <>
BS8.pack (show a) <> " " <> comp <> " " <> BS8.pack (show b)
revertMsgErr a b str comp = frameRevert $ "assertion failed: "
<> str <> ": " <> BS8.pack (show a) <> " " <> comp <> " " <> BS8.pack (show b)
assertEq abitype sig input = do
msooseth marked this conversation as resolved.
Show resolved Hide resolved
case decodeBuf [abitype, abitype] input of
CAbi [a, b] | a == b -> doStop
CAbi [a, b] -> revertErr a b "!="
_ -> vmError (BadCheatCode (paramDecodeErr abitype "assertEq") sig)
assertEqMsg abitype sig input =
case decodeBuf [abitype, abitype, AbiStringType] input of
CAbi [a, b, _] | a == b -> doStop
CAbi [a, b, AbiString str] -> revertMsgErr a b str "!="
_ -> vmError (BadCheatCode (paramDecodeMsgErr abitype "assertEq") sig)
assertNotEq abitype sig input = do
case decodeBuf [abitype, abitype] input of
CAbi [a, b] | a /= b -> doStop
CAbi [a, b] -> revertErr a b "=="
_ -> vmError (BadCheatCode (paramDecodeErr abitype "assertNotEq") sig)
assertNotEqMsg abitype sig input = do
case decodeBuf [abitype, abitype] input of
CAbi [a, b, _] | a /= b -> doStop
CAbi [a, b, AbiString str] -> revertMsgErr a b str "=="
_ -> vmError (BadCheatCode (paramDecodeMsgErr abitype "assertNotEq") sig)
assertLt abitype sig input =
case decodeBuf [abitype, abitype] input of
CAbi [a, b] | a < b -> doStop
CAbi [a, b] -> revertErr a b ">="
_ -> vmError (BadCheatCode (paramDecodeErr abitype "assertLt") sig)
assertGt abitype sig input =
case decodeBuf [abitype, abitype] input of
CAbi [a, b] | a > b -> doStop
CAbi [a, b] -> revertErr a b "<="
_ -> vmError (BadCheatCode (paramDecodeErr abitype "assertGt") sig)
assertLe abitype sig input =
case decodeBuf [abitype, abitype] input of
CAbi [a, b] | a <= b -> doStop
CAbi [a, b] -> revertErr a b "<"
_ -> vmError (BadCheatCode (paramDecodeErr abitype "assertLe") sig)
assertGe abitype sig input =
case decodeBuf [abitype, abitype] input of
CAbi [a, b] | a >= b -> doStop
CAbi [a, b] -> revertErr a b ">"
_ -> vmError (BadCheatCode (paramDecodeErr abitype "assertGe") sig)


-- * General call implementation ("delegateCall")
-- note that the continuation is ignored in the precompile case
Expand Down
26 changes: 11 additions & 15 deletions src/EVM/UnitTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import Optics.State
import Optics.State.Operators
import Data.Binary.Get (runGet)
import Data.ByteString (ByteString)
import Data.ByteString.Char8 qualified as BS
import Data.ByteString.Lazy qualified as BSLazy
import Data.Decimal (DecimalRaw(..))
import Data.Foldable (toList)
Expand Down Expand Up @@ -206,13 +207,16 @@ symRun opts@UnitTestOptions{..} vm (Sig testName types) = do
Success _ _ _ store -> failed store
_ -> PBool True
False -> \(_, post) -> case post of
Success _ _ _ store -> PNeg (failed store)
Failure _ _ (Revert msg) -> case msg of
ConcreteBuf b -> PBool $ b /= panicMsg 0x01
b -> b ./= ConcreteBuf (panicMsg 0x01)
Failure _ _ _ -> PBool True
Partial _ _ _ -> PBool True
_ -> internalError "Invalid leaf node"
Success _ _ _ store -> PNeg (failed store)
Failure _ _ (Revert msg) -> case msg of
ConcreteBuf b -> do
if (BS.isPrefixOf (BS.pack "assert failed") b) ||
b == panicMsg 0x01 then PBool True
else PBool False
b -> b ./= ConcreteBuf (panicMsg 0x01)
Failure _ _ _ -> PBool True
Partial _ _ _ -> PBool True
_ -> internalError "Invalid leaf node"

vm' <- Stepper.interpret (Fetch.oracle solvers rpcInfo) vm $
Stepper.evm $ do
Expand Down Expand Up @@ -287,14 +291,6 @@ execSymTest UnitTestOptions{ .. } method cd = do
-- Try running the test method
runExpr

checkSymFailures :: VMOps t => UnitTestOptions RealWorld -> Stepper t RealWorld (VM t RealWorld)
checkSymFailures UnitTestOptions { .. } = do
-- Ask whether any assertions failed
Stepper.evm $ do
popTrace
abiCall testParams (Left ("failed()", emptyAbi))
Stepper.runFully

Comment on lines -290 to -297
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 is not used anywhere, so I'm removing it

indentLines :: Int -> Text -> Text
indentLines n s =
let p = Text.replicate n " "
Expand Down
Loading