State of Fuzzing: Closing the Circle From Machine to Human and Back

DeFi Security Summit at Devconnect Argentina 2025 · November 2025 · 15:57

Josef Gattermayer, CEO of Ackee Blockchain Security, reviews the state of fuzzing for smart contracts. State spaces are massive and coverage-guided heuristics struggle to explore them, while manually guided fuzzing, in which auditors direct testing through flows and invariants, changed that. The talk shows how LLMs are now starting to generate such flows and invariants automatically.

Speakers

Topics

From DeFi Security Summit at Devconnect Argentina 2025, hosted by DeFi Security Summit.

Transcript

Okay. So, uh hello everyone. Uh I'm happy to share here our view on uh fuzzing. I tried to do a little bit like a summary what happened in the last year and I tried to balance it like uh to be very neutral but show some of our alpha how we do it. Uh so first of all like why we are here why why is uh fuzzing uh a problem? Of course when uh we are fuzzing smart contracts the main issue is at least from our point point of view the number of integrations which makes the state space very huge. If uh the space state space was smaller uh it

would be easy to just uh fuzz it by brute force or if anyone of you had a uh quantum computer we would not need to be solving all these uh fuzzing techniques but we are not there yet. So uh the statement is just that uh the state base is very big and the question actually is like how to find the bugs in the state space and I completely agree with uh the previous talk that uh the coverage uh the percent of the coverage is not the thing that uh helps to find the bugs that's not the metric. So we just need to focus on the techniques that help us to find the bugs where they are and not to be fuzzing that space that basically gives no value for the fuzzer. And the first let's say set of tools uh I call that like machine-driven fuzzing uh in

this category fits the black box gray box and it's basically something that you set up and let it run and the machine does everything. Uh so of course into this category fits like a medusa and this kind of stack where they are based on the two main uh techniques which is covered coverage guided uh feedback loop and then some heristics that is trying to cut also some part of the state space. So I guess you're familiar with the concept but basically like uh coverage guided feedback loop works on the principle that uh uh you put some random uh random transaction you see then uh where it got in the state space and then you are favoring uh the path that already that explored the

new code path and you're iterating over that uh over and over. The heristics it's something that basically uh is trying to uh give some more information for the fuzzer so it can make a better decisions which can be for example coming from the static analyszis uh such as slitter and uh it can give some concrete addresses or it can give some uh very edge uh values that also help the fuzzer to explore the states that are uh probably containing the bugs. So the advantage of this approach is that you set it up, you you uh let it run. Uh it's very effective in finding uh finding some bugs that the auditor

would not think about. Uh but the disadvantage why basically like we uh were not going by this approach. Uh is that sometimes the auditors they have some idea they have idea where the bug could be. And what we wanted to achieve is to be able to test this idea by the fuzzer easily not wait if the heristics or uh the state space exploration drive the fuzzer uh the direction that we want it to be. So that's the reason. Yeah. Sorry. Uh so exactly like this limitation of uh this how we call it machine approach is that the real bug can be hidden in some kind of like chain of events for example like 10 events

that have to follow each other and it's very hard for the uh horistics to get there. That's why we tried to do it a little bit differently. And the second uh part is like uh human uh guided fuzzing which uh we create a methodology we call it manual guided fuzzing and it kind of like explains what it is. So basically we wanted to give the power of guiding the fuzzer back to the hands of the auditor and not rely on heristics or uh coverage guided uh fuzzing. And basically how it works some of the principles are the same. So there are invariants but what we introduced kind

of like the new thing uh is called flow and you can understand the flow basically like an integration test uh which is telling uh which is defined by the auditor and is telling the execution path where the fuzzer should go which is exactly uh can be the complicated 10 steps that have to be done in the protocol in order to test the happy pass scenario. Uh so this is the key part of the methodology and then we have uh because we like Python so we always like implement in uh Python like a model of the protocol. It can be just a part of the protocol for example accounts. And then what we do is that we compare

outputs from the fuzzer uh and outputs from the uh contracts from the outputs of the Python state. And of course it should be even. Uh how does it look? Uh here's a very simple uh code snippet of some uh simple bridge. So basically uh we can see here that we uh create a Python state as the first two lines. Uh this is the local state that we are tracking. Uh so the model can be as simple as this. And then continues the function uh flow deposit and bridge. And this is basically the core of the flow.

Uh it's uh there is a flow decorator which basically tells this is the function that we will be randomizing for example 1,00 times. And in this function we have some uh builtin uh built-in for example features like u random account. So we select the random accounts we select the randomness then we execute the transaction and the first check is that we just uh have the state uh stateless check to see if the event was emitted successfully. So this is nothing sophisticated. It just shows that the implementation is correct. uh but the fun part begins when we here manually update uh the Python state. So basically here we updated how we think

the protocol should behave and then we define the invariant and invariant is executed after each flow. Uh and in the invariant basically here we just compare that the state of the uh of our implementation equals to the state that's returned from the contract. So this is kind of like the easiest uh example of the manually guided fuzzing as we have it implemented in wake framework. And by this basically we are giving the power to the auditor which means the auditor has to have the idea how to create this kind of like u happy pass scenario or how to create some attack vector scenario and the fuzzer just helps to test it on all accounts

with all possible inputs and this kind of randomization stuff which means in the huge state space we are not trying to cover the whole state space but we are just like very selectively selecting the path where we think uh the bugs are And of course the advantage is that we are leveraging the domain knowledge from the auditors. So basically the auditor has the idea that the fuzzer helps to execute. Uh but also we observed one quite interesting thing and it's that during the implementation of the fast test because we have to implement the model uh sometimes the auditors find the bugs that the fuzzer for example would not uh discover. But by forcing the

auditors to think about the protocol and implement some of the logic of the protocol in Python basically it opens the mind map in the head of the auditor and this process helps to find the bugs. So also like one part is the bugs from the fuzzer but one important part is the bugs that help to uh the fuzzing process helps to discover. I have some numbers here. So basically most of the issues that are discovered by the auditors when they are writing the fastest are the lo logical errors. So we have here the issues that we discovered in the last I think year. It's only high and criticals. So almost half of that are the lo logical issues. So this is the stuff that that is explored when writing the tests and then we have here data

validation the service and this is the typical stuff that is discovered by the fuzzer. So even the process that we have is like helping to uh discover the bugs. But there's a problem of course this is very time demanding because actually like we are little bit like a rewriting the protocol in Python. Uh so of course uh there's a lot of manual work for that a lot of boiler play code and also when anything changes in the contract we have to rewrite the model which is something that the clients or the protocols who are paying for our time don't really uh like. So we are thinking like how we can maybe a little bit reduce the overhead reduce the cost and that bring us to the

third category and it's like again taken control a little bit back to from humans to machine and uh we try to do some AI assisted fuzzing which we of course named wipe fuzzing and here we are trying to combine basically the two words together uh because the manually guided fuzzing works really well But there's a lot of mechanical work. So the question is like if we can kind of change it to focus only on the security logic and not on the boiler prey code. So we tried and the good thing is that v framework has a documentation and we we we also have some playbook there with lot of examples. So basically when you open cursor and just put it to the

context you know set up local uh local environment and just tell the cursor that check out the documentation look at examples it pretty much learns the framework and then we are basically able to uh generate the boiler plate code by LLM. So all the loops event handling and stuff like that is generated but of course it's hallucinating. So the important stuff needs to be checked by the auditors which in this case is mainly like the asserts. So what we are asserting because sometimes the LLMs tend to be checking things that does don't make any sense and also we need to check that the implementation of the updates of the Python model are correct

and also the auditor is usually the guy who has the idea about the execution branch or the happy pass scenario or attack vector scenario and this is the stuff that the LMS pretty suck at. They they are not able to think as an attacker. So example here basically the wipe fuzzing flow is that uh the prompt is something like create flow that mints tokens to a random recipient check that only the owner can mint verify token minted event update token state balances and it pretty correctly generates this boiler plate code. Uh so here is the flow function. Uh there is the initialization of the random parameters.

uh it does the transaction but then here where is the actual like uh event handling and where is the updates of the local Python model here it kind of like makes mistakes. So this is the part that still the auditors need to write themselves. But we have kind of solved part of the problem that uh at least half of the code now can be uh wipe coded because the LMS understand the framework and by this approach we of course reduce the main pain point which is the development speed. So now we are much more efficient in writing the model. we are able to solve by this kind of like the updates for the protocols because the LM can do it and there's still pretty good safety

net which means when there is any hallucination or anything usually it means it fails which means it produces false positive finding which we can then debug and see that okay the logic implemented by LM was wrong and u the question is if LMS can do it all so not yet but this will be of course like kind of northstar to have like you know vibe fuzzing framework that would be fully autonomous. So back to the machines we see there are like three main limitations. So uh the workflow would be easy just the AI generates the test in wake framework executes that and auditor just reviews the results. But

the main problem number one is that uh what we do during the manual guided fuzzing is basically we read the documentation and rewrite the key mathematical formulas in Python which basically means we are rewriting the protocol. So for the LLM it would need basically to wipe fast wipe wipe code the whole protocol from documentation which usually is in web 3 like sucks the documentation. So that's the main problem that the LMS basically cannot reproduce the protocol based on the data that they were given because the data are not prompts for LMS.

Uh second problem is when I touched a little bit that when the test fails still still there needs to be someone who checks if either the test is written uh incorrect or if it's a bug. So this still kind of like this triage needs to be done by humans. And uh third problem still like human creativity is the best in finding the security narratives which means usually LLMs are trained on the data that were there you know but the tech vectors are evolving are new. So this is the key input that still at least for now needs to be done by humans. But if we solve these three questions we can have fully

automated AI fuzzing. So yeah that was uh that was my talk. Uh it was quite quick I see. So uh if there are any questions you could ask me. [applause] Uh on one of your slides just now you said there's a potential for like uh so if AI makes the model then usually those bad tests are filtered out as false positives. What about when they're like not like it makes two mistakes that cancel each other out or something or like you said with the balances it reproduces the over underflow issue.

like the main problem is that the AI doesn't create the model because for for that we don't have the data such as the documentation and stuff like that or if it creates the model uh it creates the model from the solid code which is wrong because basically the idea here is that we are not affected by the solid code uh so we don't implement the possible bugs in Python so basically we have to look at it like uh uh implement the model without looking at the solici code which elements cannot do right now so basically this is the main problem in setting this workflow >> I mean like a human can also make the same mistake right which is reproduce the >> but the human can do such a things I don't know ask on a slack channel hey guys how does this work you know I'm

trying to figure out and this is the thing that uh we don't have in the in the AI workflow okay so thank you very much and see you