diff --git a/lib/Echidna/Exec.hs b/lib/Echidna/Exec.hs index 2febc9fef..264265674 100644 --- a/lib/Echidna/Exec.hs +++ b/lib/Echidna/Exec.hs @@ -6,7 +6,7 @@ module Echidna.Exec where import Control.Lens import Control.Monad (when) -import Control.Monad.Catch (MonadThrow(..)) +import Control.Monad.Catch (MonadThrow(..), catchAll, SomeException) import Control.Monad.State.Strict (MonadState(get, put), execState, runStateT, MonadIO(liftIO)) import Control.Monad.Reader (MonadReader, asks) import Data.IORef (readIORef, atomicWriteIORef) @@ -111,7 +111,7 @@ execTxWith l onErr executeTx tx = do getRpcUrl >>= \case Just rpcUrl -> do rpcBlock <- getRpcBlock - ret <- liftIO $ EVM.Fetch.fetchContractFrom rpcBlock rpcUrl addr + ret <- liftIO $ safeFetchContractFrom rpcBlock rpcUrl addr case ret of -- TODO: fix hevm to not return an empty contract in case of an error Just contract | contract._contractcode /= EVM.RuntimeCode (EVM.ConcreteRuntimeCode "") -> do @@ -153,7 +153,7 @@ execTxWith l onErr executeTx tx = do getRpcUrl >>= \case Just rpcUrl -> do rpcBlock <- getRpcBlock - ret <- liftIO $ EVM.Fetch.fetchSlotFrom rpcBlock rpcUrl addr slot + ret <- liftIO $ safeFetchSlotFrom rpcBlock rpcUrl addr slot case ret of Just value -> do l %= execState (continuation value) @@ -188,12 +188,25 @@ execTxWith l onErr executeTx tx = do getRpcUrl = liftIO $ do val <- lookupEnv "ECHIDNA_RPC_URL" pure (Text.pack <$> val) + getRpcBlock = liftIO $ do -- TODO: Is the latest block a good default? It makes fuzzing hard to -- reproduce. Rethink this. val <- lookupEnv "ECHIDNA_RPC_BLOCK" pure $ maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber (val >>= readMaybe) + -- TODO: temporary solution, handle errors gracefully + safeFetchContractFrom rpcBlock rpcUrl addr = + catchAll + (EVM.Fetch.fetchContractFrom rpcBlock rpcUrl addr) + (\(_e :: SomeException) -> pure $ Just emptyAccount) + + -- TODO: temporary solution, handle errors gracefully + safeFetchSlotFrom rpcBlock rpcUrl addr slot = + catchAll + (EVM.Fetch.fetchSlotFrom rpcBlock rpcUrl addr slot) + (\(_e :: SomeException) -> pure $ Just 0) + -- | Handles reverts, failures and contract creations that might be the result -- (`vmResult`) of executing transaction `tx`. handleErrorsAndConstruction vmResult vmBeforeTx = case (vmResult, tx.call) of