From c6c4b44af0137ccfdab8197a7dd1e4ae69114edb Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Thu, 28 Nov 2024 13:04:28 +0100 Subject: [PATCH 01/12] Fixing up prank Related to #608 --- src/EVM.hs | 52 +++++++++++++++++++++++------------------------- src/EVM/Types.hs | 4 ++-- test/test.hs | 2 +- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/EVM.hs b/src/EVM.hs index a5a83930c..77a30bade 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -83,6 +83,8 @@ blankState = do , gas = initialGas , returndata = mempty , static = False + , overrideCaller = Nothing + , resetCaller = True } -- | An "external" view of a contract's bytecode, appropriate for @@ -145,6 +147,8 @@ makeVm o = do , gas = o.gas , returndata = mempty , static = False + , overrideCaller = Nothing + , resetCaller = True } , env = env , cache = cache @@ -153,8 +157,6 @@ makeVm o = do , iterations = mempty , config = RuntimeConfig { allowFFI = o.allowFFI - , resetCaller = True - , overrideCaller = Nothing , baseState = o.baseState } , forks = Seq.singleton (ForkState env block cache "") @@ -866,17 +868,16 @@ exec1 = do forceAddr xTo' "unable to determine a call target" $ \xTo -> case gasTryFrom xGas of Left _ -> vmError IllegalOverflow - Right gas -> + Right gas -> do + overrideC <- use $ #state % #overrideCaller delegateCall this gas xTo xTo xValue xInOffset xInSize xOutOffset xOutSize xs $ \callee -> do - let from' = fromMaybe self vm.config.overrideCaller + let from' = fromMaybe self overrideC zoom #state $ do assign #callvalue xValue assign #caller from' assign #contract callee - do - resetCaller <- use (#config % #resetCaller) - when (resetCaller) $ assign (#config % #overrideCaller) Nothing + assign #overrideCaller Nothing touchAccount from' touchAccount callee transfer from' callee xValue @@ -889,14 +890,13 @@ exec1 = do forceAddr xTo' "unable to determine a call target" $ \xTo -> case gasTryFrom xGas of Left _ -> vmError IllegalOverflow - Right gas -> + Right gas -> do + overrideC <- use $ #state % #overrideCaller delegateCall this gas xTo self xValue xInOffset xInSize xOutOffset xOutSize xs $ \_ -> do zoom #state $ do assign #callvalue xValue - assign #caller $ fromMaybe self vm.config.overrideCaller - do - resetCaller <- use (#config % #resetCaller) - when (resetCaller) $ assign (#config % #overrideCaller) Nothing + assign #caller $ fromMaybe self overrideC + assign #overrideCaller Nothing touchAccount self _ -> underrun @@ -978,17 +978,16 @@ exec1 = do Just xTo' -> case gasTryFrom xGas of Left _ -> vmError IllegalOverflow - Right gas -> + Right gas -> do + overrideC <- use $ #state % #overrideCaller delegateCall this gas xTo' xTo' (Lit 0) xInOffset xInSize xOutOffset xOutSize xs $ \callee -> do zoom #state $ do assign #callvalue (Lit 0) - assign #caller $ fromMaybe self (vm.config.overrideCaller) + assign #caller $ fromMaybe self overrideC assign #contract callee assign #static True - do - resetCaller <- use (#config % #resetCaller) - when (resetCaller) $ assign (#config % #overrideCaller) Nothing + assign #overrideCaller Nothing touchAccount self touchAccount callee _ -> @@ -1101,7 +1100,9 @@ callChecks this xGas xContext xTo xValue xInOffset xInSize xOutOffset xOutSize x accessMemoryRange xOutOffset xOutSize $ do availableGas <- use (#state % #gas) let recipientExists = accountExists xContext vm - let from = fromMaybe vm.state.contract vm.config.overrideCaller + let from = fromMaybe vm.state.contract vm.state.overrideCaller + resetCaller <- use $ #state % #resetCaller + when resetCaller $ assign (#state % #overrideCaller) Nothing fromBal <- preuse $ #env % #contracts % ix from % #balance costOfCall fees recipientExists xValue availableGas xGas xTo $ \cost gas' -> do let checkCallDepth = @@ -1145,9 +1146,6 @@ callChecks this xGas xContext xTo xValue xInOffset xInSize xOutOffset xOutSize x partial $ UnexpectedSymbolicArg pc (getOpName state) "Attempting to transfer eth from a symbolic address that is not present in the state" (wrap [from]) GVar _ -> internalError "Unexpected GVar" - - - precompiledContract :: (?op :: Word8, VMOps t) => Contract @@ -1799,8 +1797,9 @@ cheatActions = Map.fromList \sig input -> case decodeStaticArgs 0 1 input of [addr] -> case wordToAddr addr of Just a -> do - assign (#config % #overrideCaller) (Just a) doStop + assign (#state % #overrideCaller) (Just a) + assign (#state % #resetCaller) True Nothing -> vmError (BadCheatCode "prank(address), could not decode address provided" sig) _ -> vmError (BadCheatCode "prank(address) parameter decoding failed" sig) @@ -1808,17 +1807,16 @@ cheatActions = Map.fromList \sig input -> case decodeStaticArgs 0 1 input of [addr] -> case wordToAddr addr of Just a -> do - assign (#config % #overrideCaller) (Just a) - assign (#config % #resetCaller) False doStop + assign (#state % #overrideCaller) (Just a) + assign (#state % #resetCaller) False Nothing -> vmError (BadCheatCode "startPrank(address), could not decode address provided" sig) _ -> vmError (BadCheatCode "startPrank(address) parameter decoding failed" sig) , action "stopPrank()" $ \_ _ -> do - assign (#config % #overrideCaller) Nothing - assign (#config % #resetCaller) True doStop + assign (#state % #overrideCaller) Nothing , action "createFork(string)" $ \sig input -> case decodeBuf [AbiStringType] input of @@ -1993,7 +1991,6 @@ delegateCall this gasGiven xTo xContext xValue xInOffset xInSize xOutOffset xOut pushTrace (FrameTrace newContext) next vm1 <- get - pushTo #frames $ Frame { state = vm1.state { stack = xs } , context = newContext @@ -2014,6 +2011,7 @@ delegateCall this gasGiven xTo xContext xValue xInOffset xInSize xOutOffset xOut assign #memorySize 0 assign #returndata mempty assign #calldata calldata + assign #overrideCaller Nothing continue xTo -- -- * Contract creation diff --git a/src/EVM/Types.hs b/src/EVM/Types.hs index d03f2ee94..90f3426c7 100644 --- a/src/EVM/Types.hs +++ b/src/EVM/Types.hs @@ -665,8 +665,6 @@ data BaseState -- | Configuration options that need to be consulted at runtime data RuntimeConfig = RuntimeConfig { allowFFI :: Bool - , overrideCaller :: Maybe (Expr EAddr) - , resetCaller :: Bool , baseState :: BaseState } deriving (Show) @@ -728,6 +726,8 @@ data FrameState (t :: VMType) s = FrameState , gas :: !(Gas t) , returndata :: Expr Buf , static :: Bool + , overrideCaller :: Maybe (Expr EAddr) + , resetCaller :: Bool } deriving (Generic) diff --git a/test/test.hs b/test/test.hs index b428670cd..7a0c3df8a 100644 --- a/test/test.hs +++ b/test/test.hs @@ -1231,7 +1231,7 @@ tests = testGroup "hevm" Right e <- reachableUserAsserts c (Just $ Sig "f(address,uint256)" [AbiAddressType, AbiUIntType 256]) assertBoolM "The expression is not partial" $ Expr.containsNode isPartial e , - test "vm.prank underflow" $ do + test "vm.prank-underflow" $ do Just c <- solcRuntime "C" [i| interface Vm { From 1dc2e9e96e741b25581c07b7580146afdf1b8676 Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Thu, 28 Nov 2024 18:13:30 +0100 Subject: [PATCH 02/12] Updating changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccfdf87a1..26eaa328a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Respect --smt-timeout in equivalence checking - Fixed the handling of returndata with an abstract size during transaction finalization - Error handling for user-facing cli commands is much improved +- Fixing prank so it doesn't override the sender address on lower call frames ## [0.53.0] - 2024-02-23 From b9891e6b9822d6f5aee2f0eb0dcc114decdb79f5 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:08:20 +0100 Subject: [PATCH 03/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EVM.hs b/src/EVM.hs index 77a30bade..02b90f4e2 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -84,7 +84,7 @@ blankState = do , returndata = mempty , static = False , overrideCaller = Nothing - , resetCaller = True + , resetCaller = False } -- | An "external" view of a contract's bytecode, appropriate for From 499910b6469563e8a0138d4e28398312c2b6d937 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:08:42 +0100 Subject: [PATCH 04/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EVM.hs b/src/EVM.hs index 02b90f4e2..248fc7a0e 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -148,7 +148,7 @@ makeVm o = do , returndata = mempty , static = False , overrideCaller = Nothing - , resetCaller = True + , resetCaller = False } , env = env , cache = cache From 4ad7fbd02138b865986be028006f16c3a1b26347 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:09:11 +0100 Subject: [PATCH 05/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EVM.hs b/src/EVM.hs index 248fc7a0e..975e1bac4 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -878,6 +878,7 @@ exec1 = do assign #caller from' assign #contract callee assign #overrideCaller Nothing + assign #resetCaller False touchAccount from' touchAccount callee transfer from' callee xValue From 79fa12a6c4205cfdb4963fe359f8cf9f2831f9ba Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:09:23 +0100 Subject: [PATCH 06/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EVM.hs b/src/EVM.hs index 975e1bac4..7a4bc41a6 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -898,6 +898,7 @@ exec1 = do assign #callvalue xValue assign #caller $ fromMaybe self overrideC assign #overrideCaller Nothing + assign #resetCaller False touchAccount self _ -> underrun From c960726d9df30a2f001a7f1b8029b3268501c9b6 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:09:32 +0100 Subject: [PATCH 07/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EVM.hs b/src/EVM.hs index 7a4bc41a6..60eb88f14 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -990,6 +990,7 @@ exec1 = do assign #contract callee assign #static True assign #overrideCaller Nothing + assign #resetCaller False touchAccount self touchAccount callee _ -> From fba5a264bc83d8de9991c6836f157b79ced75380 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:10:16 +0100 Subject: [PATCH 08/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EVM.hs b/src/EVM.hs index 60eb88f14..e6cbfa2a3 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -2015,6 +2015,7 @@ delegateCall this gasGiven xTo xContext xValue xInOffset xInSize xOutOffset xOut assign #returndata mempty assign #calldata calldata assign #overrideCaller Nothing + assign #resetCaller False continue xTo -- -- * Contract creation From e7e7c311588e2040d964cfaf8d313f6bd0ec5d42 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Ethereum Foundation" <99662964+msooseth@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:11:24 +0100 Subject: [PATCH 09/12] Update src/EVM.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emilio López <2642849+elopez@users.noreply.github.com> --- src/EVM.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EVM.hs b/src/EVM.hs index e6cbfa2a3..5a704e270 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -1820,6 +1820,7 @@ cheatActions = Map.fromList \_ _ -> do doStop assign (#state % #overrideCaller) Nothing + assign (#state % #resetCaller) False , action "createFork(string)" $ \sig input -> case decodeBuf [AbiStringType] input of From 665ccacd4463e0ab03e873ab0ef01506ff1b3bfb Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Mon, 2 Dec 2024 10:39:14 +0100 Subject: [PATCH 10/12] Let's not have trailing whitespace --- src/EVM.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EVM.hs b/src/EVM.hs index 5a704e270..46898c4fa 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -878,7 +878,7 @@ exec1 = do assign #caller from' assign #contract callee assign #overrideCaller Nothing - assign #resetCaller False + assign #resetCaller False touchAccount from' touchAccount callee transfer from' callee xValue From 0371caffa3b6e816e97d1740a7b3412426f682c8 Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Mon, 2 Dec 2024 11:55:36 +0100 Subject: [PATCH 11/12] Moving resetCaller update to delegateCall --- src/EVM.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EVM.hs b/src/EVM.hs index 46898c4fa..649f67477 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -1104,8 +1104,6 @@ callChecks this xGas xContext xTo xValue xInOffset xInSize xOutOffset xOutSize x availableGas <- use (#state % #gas) let recipientExists = accountExists xContext vm let from = fromMaybe vm.state.contract vm.state.overrideCaller - resetCaller <- use $ #state % #resetCaller - when resetCaller $ assign (#state % #overrideCaller) Nothing fromBal <- preuse $ #env % #contracts % ix from % #balance costOfCall fees recipientExists xValue availableGas xGas xTo $ \cost gas' -> do let checkCallDepth = @@ -1971,6 +1969,8 @@ delegateCall this gasGiven xTo xContext xValue xInOffset xInSize xOutOffset xOut | otherwise = callChecks this gasGiven xContext xTo xValue xInOffset xInSize xOutOffset xOutSize xs $ \xGas -> do + resetCaller <- use $ #state % #resetCaller + when resetCaller $ assign (#state % #overrideCaller) Nothing vm0 <- get fetchAccount xTo $ \target -> case target.code of UnknownCode _ -> do From 6d61bb6a2d7274961146778946727f1f072f7541 Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Mon, 2 Dec 2024 12:48:02 +0100 Subject: [PATCH 12/12] No need for these, it's already been set Thanks to @elopez for this --- src/EVM.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/EVM.hs b/src/EVM.hs index 649f67477..fd39edb20 100644 --- a/src/EVM.hs +++ b/src/EVM.hs @@ -877,8 +877,6 @@ exec1 = do assign #callvalue xValue assign #caller from' assign #contract callee - assign #overrideCaller Nothing - assign #resetCaller False touchAccount from' touchAccount callee transfer from' callee xValue @@ -897,8 +895,6 @@ exec1 = do zoom #state $ do assign #callvalue xValue assign #caller $ fromMaybe self overrideC - assign #overrideCaller Nothing - assign #resetCaller False touchAccount self _ -> underrun @@ -989,8 +985,6 @@ exec1 = do assign #caller $ fromMaybe self overrideC assign #contract callee assign #static True - assign #overrideCaller Nothing - assign #resetCaller False touchAccount self touchAccount callee _ ->