Skip to content

Commit 740e950

Browse files
authored
Allow disabling Slither (#1327)
This allows explicitly disabling Slither with a new `--disable-slither` command-line flag or `disableSlither` configuration option. A blinking, red warning will be shown in the UI when Slither is disabled or otherwise failed, to disuade people from fuzzing without it. Closes #1318
1 parent 0db6f4c commit 740e950

File tree

7 files changed

+38
-4
lines changed

7 files changed

+38
-4
lines changed

lib/Echidna/Config.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ instance FromJSON EConfigWithUsage where
114114
<*> v ..:? "balanceContract" ..!= 0
115115
<*> v ..:? "codeSize" ..!= 0xffffffff
116116
<*> v ..:? "prefix" ..!= "echidna_"
117+
<*> v ..:? "disableSlither" ..!= False
117118
<*> v ..:? "cryticArgs" ..!= []
118119
<*> v ..:? "solcArgs" ..!= ""
119120
<*> v ..:? "solcLibs" ..!= []

lib/Echidna/SourceAnalysis/Slither.hs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,13 @@ instance FromJSON SlitherInfo where
145145

146146
-- Slither processing
147147
runSlither :: FilePath -> SolConf -> IO SlitherInfo
148-
runSlither fp solConf = do
149-
findExecutable "slither" >>= \case
148+
runSlither fp solConf = if solConf.disableSlither
149+
then do
150+
hPutStrLn stderr $
151+
"WARNING: Slither was explicitly disabled. Echidna uses Slither (https://github.com/crytic/slither)"
152+
<> " to perform source analysis, which makes fuzzing more effective. You should enable it."
153+
pure emptySlitherInfo
154+
else findExecutable "slither" >>= \case
150155
Nothing -> do
151156
hPutStrLn stderr $
152157
"WARNING: slither not found. Echidna uses Slither (https://github.com/crytic/slither)"
@@ -177,3 +182,8 @@ runSlither fp solConf = do
177182

178183
emptySlitherInfo :: SlitherInfo
179184
emptySlitherInfo = SlitherInfo mempty mempty mempty mempty mempty [] [] []
185+
186+
isEmptySlitherInfo :: Maybe SlitherInfo -> Bool
187+
isEmptySlitherInfo (Just (SlitherInfo _ _ _ _ _ [] [] [])) = True
188+
isEmptySlitherInfo Nothing = True
189+
isEmptySlitherInfo _ = False

lib/Echidna/Types/Solidity.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ data SolConf = SolConf
6666
, balanceContract :: Integer -- ^ Initial balance of contract to test
6767
, codeSize :: Integer -- ^ Max code size for deployed contratcs (default 0xffffffff)
6868
, prefix :: Text -- ^ Function name prefix used to denote tests
69+
, disableSlither :: Bool -- ^ Whether or not to skip running Slither
6970
, cryticArgs :: [String] -- ^ Args to pass to crytic
7071
, solcArgs :: String -- ^ Args to pass to @solc@
7172
, solcLibs :: [String] -- ^ List of libraries to load, in order.

lib/Echidna/UI.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import Echidna.Campaign (runWorker, spawnListener)
3636
import Echidna.Output.Corpus (saveCorpusEvent)
3737
import Echidna.Output.JSON qualified
3838
import Echidna.Server (runSSEServer)
39+
import Echidna.SourceAnalysis.Slither (isEmptySlitherInfo)
3940
import Echidna.Types.Campaign
4041
import Echidna.Types.Config
4142
import Echidna.Types.Corpus qualified as Corpus
@@ -126,6 +127,7 @@ ui vm dict initialCorpus cliSelectedContract = do
126127
, timeStarted = now
127128
, timeStopped = Nothing
128129
, now = now
130+
, slitherSucceeded = not $ isEmptySlitherInfo env.slitherInfo
129131
, fetchedContracts = mempty
130132
, fetchedSlots = mempty
131133
, fetchedDialog = B.dialog (Just $ str " Fetched contracts/slots ") Nothing 80

lib/Echidna/UI/Widgets.hs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ data UIState = UIState
4242
, timeStarted :: LocalTime
4343
, timeStopped :: Maybe LocalTime
4444
, now :: LocalTime
45+
, slitherSucceeded :: Bool
4546
, fetchedContracts :: Map Addr (Maybe Contract)
4647
, fetchedSlots :: Map Addr (Map W256 (Maybe W256))
4748
, fetchedDialog :: B.Dialog () Name
@@ -65,7 +66,8 @@ data UIStateStatus = Uninitialized | Running
6566

6667
attrs :: A.AttrMap
6768
attrs = A.attrMap (V.white `on` V.black)
68-
[ (attrName "failure", fg V.brightRed)
69+
[ (attrName "alert", fg V.brightRed `V.withStyle` V.blink `V.withStyle` V.bold)
70+
, (attrName "failure", fg V.brightRed)
6971
, (attrName "maximum", fg V.brightBlue)
7072
, (attrName "bold", fg V.white `V.withStyle` V.bold)
7173
, (attrName "tx", fg V.brightWhite)
@@ -79,6 +81,9 @@ attrs = A.attrMap (V.white `on` V.black)
7981
bold :: Widget n -> Widget n
8082
bold = withAttr (attrName "bold")
8183

84+
alert :: Widget n -> Widget n
85+
alert = withAttr (attrName "alert")
86+
8287
failure :: Widget n -> Widget n
8388
failure = withAttr (attrName "failure")
8489

@@ -184,6 +189,8 @@ summaryWidget env uiState =
184189
str ("Corpus size: " <> show uiState.corpusSize <> " seqs")
185190
<=>
186191
str ("New coverage: " <> timeElapsed uiState uiState.lastNewCov <> " ago") <+> fill ' '
192+
<=>
193+
slitherWidget uiState.slitherSucceeded
187194
rightSide =
188195
padLeft (Pad 1)
189196
(rpcInfoWidget uiState.fetchedContracts uiState.fetchedSlots env.chainId)
@@ -217,6 +224,13 @@ rpcInfoWidget contracts slots chainId =
217224
let successful = filter isJust fetches
218225
in outOf (length successful) (length fetches)
219226

227+
slitherWidget
228+
:: Bool
229+
-> Widget Name
230+
slitherWidget slitherSucceeded = if slitherSucceeded
231+
then success (str "Slither succeeded")
232+
else alert (str "No Slither in use!")
233+
220234
outOf :: Int -> Int -> Widget n
221235
outOf n m =
222236
let style = if n == m then success else failure

src/Main.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ data Options = Options
135135
, cliDeployer :: Maybe Addr
136136
, cliSender :: [Addr]
137137
, cliSeed :: Maybe Int
138+
, cliDisableSlither :: Bool
138139
, cliCryticArgs :: Maybe String
139140
, cliSolcArgs :: Maybe String
140141
, cliSymExec :: Maybe Bool
@@ -210,6 +211,8 @@ options = Options
210211
<*> optional (option auto $ long "seed"
211212
<> metavar "SEED"
212213
<> help "Run with a specific seed.")
214+
<*> switch (long "disable-slither"
215+
<> help "Disable running Slither.")
213216
<*> optional (option str $ long "crytic-args"
214217
<> metavar "ARGS"
215218
<> help "Additional arguments to use in crytic-compile for the compilation of the contract to test.")
@@ -276,7 +279,8 @@ overrideConfig config Options{..} = do
276279
}
277280

278281
overrideSolConf solConf = solConf
279-
{ solcArgs = fromMaybe solConf.solcArgs cliSolcArgs
282+
{ disableSlither = cliDisableSlither || solConf.disableSlither
283+
, solcArgs = fromMaybe solConf.solcArgs cliSolcArgs
280284
, cryticArgs = maybe solConf.cryticArgs words cliCryticArgs
281285
, sender = if null cliSender then solConf.sender else Set.fromList cliSender
282286
, deployer = fromMaybe solConf.deployer cliDeployer

tests/solidity/basic/default.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ balanceAddr: 0xffffffff
4040
balanceContract: 0
4141
#codeSize max code size for deployed contratcs (default 0xffffffff)
4242
codeSize: 0xffffffff
43+
#whether or not to disable running slither (default false, uses slither)
44+
disableSlither: false
4345
#solcArgs allows special args to solc
4446
solcArgs: ""
4547
#solcLibs is solc libraries

0 commit comments

Comments
 (0)