Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback on fuzzer benchmarking setup #103

Open
wuestholz opened this issue Mar 23, 2023 · 2 comments
Open

Feedback on fuzzer benchmarking setup #103

wuestholz opened this issue Mar 23, 2023 · 2 comments

Comments

@wuestholz
Copy link

I'm trying to compare Hybrid-Echidna with Echidna and the Forge fuzzer on several benchmark contracts.

To make the comparison as fair as possible, I've created a benchmark generator that automatically generates challenging contracts. The benchmarks intentionally use a limited subset of Solidity to avoid language features that could be handled differently by different tools. Each contract contains ~50 assertions (some can fail, but others cannot due to infeasible path conditions). (If you're curious, you can find one of the benchmarks here. The benchmark-generation approach is inspired by the Fuzzle benchmark generator for C-based fuzzers.) To find the assertions that can fail, a fuzzer needs to generate up to ~15 transactions and satisfy some input constraints for each transaction.

Since I'm not deeply familiar with Hybrid-Echidna I'd like to check if there are any potential issues with my benchmark setup before sharing results.

Since Hybrid-Echidna does not support limiting the execution time (see issue at #101), I'm repeatedly running the fuzzer for shorter periods until the time limit for all fuzzers (for instance, 1 hour for each contract). For each of these shorter fuzzing campaigns I'm using the following settings that deviate from the defaults:

  • seq-len: 100 (instead of 10)
  • test-limit: 50000 for the first short campaign and 500 for all subsequent ones (instead of 50000)
  • max-iters: 3 for the first short campaign and 1 for all subsequent ones (instead of leaving the option unspecified)
  • no-incremental: false for the first short campaign and true for all subsequent ones (instead of false)
  • codeSize (Echidna): 0xc00000 (instead of 0x6000)

I increased seq-len to 100 since some assertions may require up to ~15 transactions, and some generated transactions may fail. Echidna uses 100 by default.

I observed very high memory consumption when leaving max-iters unspecified or using larger values. For this reason, I bound the number of iterations.

I reduced test-limit to make sure that the short campaigns terminate reasonably fast. I also observed increased memory consumption for larger values.

I enable no-incremental for subsequent short campaigns since the first campaign will have already performed incremental seeding once.

I also increased the codeSize setting to handle larger contracts, if necessary. Currently, all benchmark contracts are below the EVM limit when using the solc optimizer (0.8.19).

Somewhat surprisingly, Echidna performs much better on these benchmarks than Hybrid-Echidna. It would be great to understand why. For instance, I tried setting a solver timeout. However, this did not have a noticable effect on the fuzzing performance.

Please let me know if you see any potential issues with this setup.

@ggrieco-tob
Copy link
Member

Hybrid-Echidna is a very experimental tool. I'm afraid we don't have enough information to fully guide your research. However, it is clear that since optik relies on SMT solvers (which can fail or timeout with some queries), then reducing the queries complexity is needed. In particular, the sequence of transaction length should be reduced (100 is extremely large can result of very high memory consumption).

We haven't experimented enough with optik, but I personally think that using hybrid-echidna should be used first with a small numbers of consecutive transactions (e.g. seqLen equal to 10 or 5). This should help to explore "difficult" inputs. Once this scenario is fully explored, the corpus should be provided to Echidna for a larger campaign (e.g using seqLen as 100). Keep in mind that once you do this, you cannot use optik again. Sadly, we do not have anything "automatic" developed for this particular case. Happy to discuss your results using this tool.

@wuestholz
Copy link
Author

@ggrieco-tob Thanks a lot!

I used a smaller sequence length (30) before, but the increase to 100 didn't negatively affect the performance. Is the size of the SMT constraints proportional to the sequence length? I somehow assumed that only a few transactions would be executed with symbolic inputs to prevent a blowup.

For instance, one way to interpret your suggestion is to only make the first K (e.g., 5 or 10) transactions symbolic. In that case, a longer sequence list with lots of concrete transactions should not hurt. Have you considered this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants