From a7303dd71e0ca847407ba3b50d1c92c4fe130025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 6 Jun 2025 23:02:08 -0300 Subject: [PATCH] Add benchmark mode that does not filter by prefix Fixes: #1347 --- lib/Echidna/Solidity.hs | 26 +++++++++++++++++--------- lib/Echidna/Test.hs | 9 ++++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lib/Echidna/Solidity.hs b/lib/Echidna/Solidity.hs index d83ac235c..f903c4f78 100644 --- a/lib/Echidna/Solidity.hs +++ b/lib/Echidna/Solidity.hs @@ -43,7 +43,7 @@ import Echidna.Etheno (loadEthenoBatch) import Echidna.Events (extractEvents) import Echidna.Exec (execTx, execTxWithCov, initialVM) import Echidna.SourceAnalysis.Slither -import Echidna.Test (createTests, isAssertionMode, isPropertyMode, isDapptestMode) +import Echidna.Test (createTests, isAssertionMode, isPropertyMode, isDapptestMode, isBenchmarkMode) import Echidna.Types.Campaign (CampaignConf(..)) import Echidna.Types.Config (EConfig(..), Env(..)) import Echidna.Types.Signature @@ -155,11 +155,16 @@ filterMethodsWithArgs ms = [] -> error "No dapptest tests found" fs -> NE.fromList fs +fullAbiOf :: SolcContract -> NonEmpty SolSignature +fullAbiOf solcContract = + fallback :| + (Map.elems solcContract.abiMap <&> \method -> (method.name, snd <$> method.inputs)) + abiOf :: Text -> SolcContract -> NonEmpty SolSignature abiOf pref solcContract = fallback :| filter (not . isPrefixOf pref . fst) - (Map.elems solcContract.abiMap <&> \method -> (method.name, snd <$> method.inputs)) + (NE.tail $ fullAbiOf solcContract) -- | Given an optional contract name and a list of 'SolcContract's, try to load the specified -- contract, or, if not provided, the first contract in the list, into a 'VM' usable for Echidna @@ -262,17 +267,20 @@ mkSignatureMap mkSignatureMap solConf mainContract contracts = do let -- Filter ABI according to the config options - fabiOfc = if isDapptestMode solConf.testMode - then NE.toList $ filterMethodsWithArgs (abiOf solConf.prefix mainContract) - else filterMethods mainContract.contractName solConf.methodFilter $ - abiOf solConf.prefix mainContract + fabiOfc + | isDapptestMode solConf.testMode = NE.toList $ filterMethodsWithArgs (abiOf solConf.prefix mainContract) + | isBenchmarkMode solConf.testMode = NE.toList $ fullAbiOf mainContract + | otherwise = filterMethods mainContract.contractName solConf.methodFilter $ + abiOf solConf.prefix mainContract -- Construct ABI mapping for World abiMapping = if solConf.allContracts then Map.fromList $ mapMaybe (\contract -> - let filtered = filterMethods contract.contractName - solConf.methodFilter - (abiOf solConf.prefix contract) + let filtered = if isBenchmarkMode solConf.testMode + then NE.toList $ fullAbiOf contract + else filterMethods contract.contractName + solConf.methodFilter + (abiOf solConf.prefix contract) in (contract.runtimeCodehash,) <$> NE.nonEmpty filtered) contracts else diff --git a/lib/Echidna/Test.hs b/lib/Echidna/Test.hs index c0fbb13db..670c36aa2 100644 --- a/lib/Echidna/Test.hs +++ b/lib/Echidna/Test.hs @@ -54,7 +54,7 @@ createTest m = EchidnaTest Open m v [] Stop Nothing Nothing validateTestModeError :: String validateTestModeError = - "Invalid test mode (should be property, assertion, dapptest, optimization, overflow or exploration)" + "Invalid test mode (should be property, assertion, dapptest, optimization, overflow, exploration or benchmark)" validateTestMode :: String -> TestMode validateTestMode s = case s of @@ -64,6 +64,7 @@ validateTestMode s = case s of "exploration" -> s "overflow" -> s "optimization" -> s + "benchmark" -> s _ -> error validateTestModeError isAssertionMode :: TestMode -> Bool @@ -82,6 +83,10 @@ isDapptestMode :: TestMode -> Bool isDapptestMode "dapptest" = True isDapptestMode _ = False +isBenchmarkMode :: TestMode -> Bool +isBenchmarkMode "benchmark" = True +isBenchmarkMode _ = False + createTests :: TestMode -> Bool @@ -92,6 +97,8 @@ createTests createTests m td ts r ss = case m of "exploration" -> [createTest Exploration] + "benchmark" -> + [createTest Exploration] "overflow" -> [createTest (CallTest "Integer (over/under)flow" checkOverflowTest)] "property" ->