@@ -19,13 +19,15 @@ import Data.IORef (IORef, writeIORef, readIORef, atomicModifyIORef')
1919import Data.Map (Map )
2020import qualified Data.Map as Map
2121import qualified Data.Set as Set
22+ import Data.Text (Text )
2223import System.Directory (getCurrentDirectory )
2324
2425import Echidna.Output.Source (saveLcovHook )
2526import EVM.Dapp (DappInfo (.. ))
2627import EVM.Types (VM (.. ), VMType (Concrete ), Expr (.. ), EType (.. ), Contract )
2728import qualified EVM.Types as EVM
2829
30+ import EVM.ABI (AbiValue )
2931import Echidna.ABI (GenDict (.. ))
3032import Echidna.Execution (replayCorpus , callseq , updateTests )
3133import Echidna.Mutator.Corpus (getCorpusMutation , seqMutatorsStateless , seqMutatorsStateful , fromConsts )
@@ -226,59 +228,90 @@ randseq
226228 => Map (Expr 'EAddr) Contract
227229 -> m [Tx ]
228230randseq deployedContracts = do
229- env <- ask
230- let world = env. world
231-
232- let
233- mutConsts = env. cfg. campaignConf. mutConsts
234- seqLen = env. cfg. campaignConf. seqLen
235-
231+ -- 1. Check for prioritized sequences injected via tools
236232 prioritized <- gets (. prioritizedSequences)
237233
238234 mbSeq <- if null prioritized
239235 then pure Nothing
240236 else do
237+ -- Select a prioritized sequence based on probability
241238 (prob, seqPrototype) <- rElem (NE. fromList prioritized)
242239 useIt <- (<= prob) <$> getRandom
243240 pure $ if useIt then Just seqPrototype else Nothing
244241
245242 case mbSeq of
246- Just seqPrototype -> do
243+ Just seqPrototype -> genPrioritizedSeq deployedContracts seqPrototype
244+ Nothing -> genStandardSeq deployedContracts
245+
246+ -- | Generate a sequence of transactions based on a prioritized prototype
247+ genPrioritizedSeq
248+ :: (MonadRandom m , MonadReader Env m , MonadState WorkerState m , MonadIO m )
249+ => Map (Expr 'EAddr) Contract
250+ -> [(Text , [Maybe AbiValue ])]
251+ -> m [Tx ]
252+ genPrioritizedSeq deployedContracts seqPrototype = do
253+ env <- ask
254+ let world = env. world
255+ seqLen = env. cfg. campaignConf. seqLen
256+
257+ -- 2. If a prioritized sequence is selected:
258+ -- Expand the prototype into concrete transactions
247259 let expandPrototype [] = return []
248260 expandPrototype [p] = do
249261 tx <- genTxFromPrototype world deployedContracts p
250262 return [tx]
251263 expandPrototype (p: ps) = do
252264 tx <- genTxFromPrototype world deployedContracts p
265+ -- Insert random transactions between prototype transactions to increase fuzzing diversity
253266 n <- getRandomR (0 , 3 )
254267 rndTxs <- replicateM n (genTx world deployedContracts)
255268 rest <- expandPrototype ps
256269 return ((tx : rndTxs) ++ rest)
257270
258271 expandedTxs <- expandPrototype seqPrototype
259272 corpusSet <- liftIO $ readIORef env. corpusRef
260- prefix <- if Set. null corpusSet
273+ wid <- gets (. workerId)
274+
275+ -- Select a prefix from the existing corpus
276+ -- Special handling for worker 0: always use empty prefix (position 0)
277+ prefix <- if Set. null corpusSet || wid == 0
261278 then pure []
262279 else do
280+ -- Pick a random sequence from corpus
263281 idx <- getRandomR (0 , Set. size corpusSet - 1 )
264282 let (_, cTxs) = Set. elemAt idx corpusSet
265283 let middleLen = length expandedTxs
266284 let maxPrefix = seqLen - middleLen
267285 if maxPrefix <= 0
268286 then pure []
269287 else do
288+ -- Take a random prefix length
270289 k <- getRandomR (0 , min (length cTxs) maxPrefix)
271290 pure (take k cTxs)
272291
273292 let combined = prefix ++ expandedTxs
274293 let len = length combined
294+
295+ -- Pad with random transactions if sequence is too short
275296 if len < seqLen
276297 then do
277298 paddingTxs <- replicateM (seqLen - len) (genTx world deployedContracts)
278299 pure (combined ++ paddingTxs)
279300 else
280301 pure (take seqLen combined)
281- Nothing -> do
302+
303+ -- | Generate a sequence of transactions using standard fuzzing techniques
304+ genStandardSeq
305+ :: (MonadRandom m , MonadReader Env m , MonadState WorkerState m , MonadIO m )
306+ => Map (Expr 'EAddr) Contract
307+ -> m [Tx ]
308+ genStandardSeq deployedContracts = do
309+ env <- ask
310+ let world = env. world
311+ mutConsts = env. cfg. campaignConf. mutConsts
312+ seqLen = env. cfg. campaignConf. seqLen
313+
314+ -- 3. Standard fuzzing behavior (no prioritized sequence selected)
282315 -- Generate new random transactions
283316 randTxs <- replicateM seqLen (genTx world deployedContracts)
284317 -- Generate a random mutator
0 commit comments