Skip to content

Commit

Permalink
Merge pull request #609 from ethereum/fix_prank
Browse files Browse the repository at this point in the history
Fixing prank: no longer override the sender on lower frames
  • Loading branch information
msooseth authored Dec 2, 2024
2 parents 0a21109 + 6d61bb6 commit ee906ef
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
51 changes: 24 additions & 27 deletions src/EVM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ blankState = do
, gas = initialGas
, returndata = mempty
, static = False
, overrideCaller = Nothing
, resetCaller = False
}

-- | An "external" view of a contract's bytecode, appropriate for
Expand Down Expand Up @@ -145,6 +147,8 @@ makeVm o = do
, gas = o.gas
, returndata = mempty
, static = False
, overrideCaller = Nothing
, resetCaller = False
}
, env = env
, cache = cache
Expand All @@ -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 "")
Expand Down Expand Up @@ -866,17 +868,15 @@ 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
touchAccount from'
touchAccount callee
transfer from' callee xValue
Expand All @@ -889,14 +889,12 @@ 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
touchAccount self
_ ->
underrun
Expand Down Expand Up @@ -978,17 +976,15 @@ 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
touchAccount self
touchAccount callee
_ ->
Expand Down Expand Up @@ -1101,7 +1097,7 @@ 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
fromBal <- preuse $ #env % #contracts % ix from % #balance
costOfCall fees recipientExists xValue availableGas xGas xTo $ \cost gas' -> do
let checkCallDepth =
Expand Down Expand Up @@ -1145,9 +1141,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
Expand Down Expand Up @@ -1799,26 +1792,27 @@ 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)

, action "startPrank(address)" $
\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
assign (#state % #resetCaller) False

, action "createFork(string)" $
\sig input -> case decodeBuf [AbiStringType] input of
Expand Down Expand Up @@ -1969,6 +1963,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
Expand All @@ -1993,7 +1989,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
Expand All @@ -2014,6 +2009,8 @@ delegateCall this gasGiven xTo xContext xValue xInOffset xInSize xOutOffset xOut
assign #memorySize 0
assign #returndata mempty
assign #calldata calldata
assign #overrideCaller Nothing
assign #resetCaller False
continue xTo

-- -- * Contract creation
Expand Down
4 changes: 2 additions & 2 deletions src/EVM/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion test/test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit ee906ef

Please sign in to comment.