Welcome to Isa to Ethan to Ethan to Isa to Isa. Um, first of all, hello to everyone. Um, this is basically like a case study of the work we've been doing in Enigma for D5 protocols, but wrapped in a talk in some way. So, um, yes, maybe a little bit of background. I'm Victor Martinez.
I've been doing like fuzzing and blockchain security stuff for I don't know three years or four years already and last year we founded Nick Madark way and I he's here and uh we do like top tier security service uh security services for protocols mostly and one of those is fuzzing. So what exactly is fuzzing? Fuzzing is just taking a program and um throwing random inputs at it while you monitor like um assertions or stuff breaking into the into the program. Right? So you you have your fuzzing tool, you have the um in this case the program is a an Ethereum smart contract.
So we have the fuzzer calling the Ethereum smart contract and then we implement a few different checks to make sure that everything runs as expected and that way we can start doing invariant testing using fuzzing because invariant testing is basically just checking those invarants into like um a whole lot of states. For tooling uh for tooling we will go over the main tooling for fing um the usual one is foundry is the most used one uh but it's only useful for the stateless tests I think like so far compared to the other two tools um so for stateless tests we have foundry the same way you can do like you do a unit test in foundry you can do like a fast test with foundry as well so it's pretty straightforward and then we have medusa and akina those are the most interesting tools because we can wrap like the behavior of the tools into a framework into an actor-based framework to simulate everything that could happen in real life on a on a protocol but uh locally with the tools so we don't have to get hacked we can prevent the bugs um so yeah basically we use a kin and medusa and we always recommend to use those if you want to use the same setup and the same framework that you would or the way of the reasoning behind it that we use uh so the case study we've been working with uh a for the B3 oiler for for V2, Zilo 4D3 and many other protocols. I just have a few here. So we will see some cases, some interesting stuff that we found and or maybe some concerns that we were able to find with uh with um with this technique fuzzing and invariant testing. So what's an invarian?
An imbarian suite like a suite of tests but um you have here you have here what would be like an abstracted version of a protocol. some maybe a whole deployment of the AB B3 protocol and then we have like a suite of tests. It's basically just one contract inheriting all the functionality for the suite uh to work and the most important part of the suite are the actors. The actors are just uh like some kind of proxies for the tool. The tool uses like random addresses like a set of predefined addresses to call the the the harnesses in this uh context.
So basically this just uh wraps everything and let's uh they act similar to a smart accounts in some way. So they are smart contracts and they just interact with the protocol and we can assert stuff. We can um basically call everything on the protocol from the suite from the harnesses and check a lot of stuff. Also another thing to mention regarding the difference between Foundry and Medusa and Akina is that Foundry um these tools in order to work really good. They they have something called um path exploring or coverage guidance.
And basically whenever they run each time they run they run at least a bit more efficient or they are able to find like more paths into the protocol or into the into the system because they just store and like learn from um previous runs. So that's like a huge uh thing about Akina especially Kina I usually use we usually use Akina. So um yeah and we have like a different types of modes that we will cover later. So yeah types of properties on the framework on the enigma framework really similar to what other companies are doing like mostly formal verification companies because we don't like to make that many unit tests. We think that global invariance stuff like uh the total balance of the protocol should be equal to the sum of the user balances.
Uh that's a global invariant and those are the ones we tend to focus the most on because then you can just assert stuff like that and um get to a state that breaks that invariant and then uh roll back like kind of engineer back everything or debug everything into the like the root cause. You don't have to go explicitly for the root cause. Then we have the global post conditions. Here we just cache values before and after the calls and then compare. It's like asserting rules on state transitions instead of on the states directly.
And then specific 100 specific post conditions are just some specific stuff. For example, if I have one rule for liquidations on a liquidation function, I don't want maybe I don't want that rule to to be checked on deposits or on withdrawals or stuff like that. Um so yeah, let's go get straight into Oiler. uh oiler for the EVK for the if you are not aware of it it's like the a new super modular and uh super interesting lending protocol and it's um everything works like on a um with the EBC and with the ABK the EBK is the framework that you can build or use it uh to make lending protocols yourself or but integrated with oiler of course um yes so the main variant on lending protocols we try to abstract everything in classes in back classes or in areas. So one of them is the availability of the functions.
We want uh repayment functions to always be collable to never be in a dosed uh like in a dos state. So basically we were with this with a suite we built for oiler we were able to find some specific edge case uh simulating all the functions on the protocol some specific edge case that uh made users not able to repay depth in some case obviously this is in like an early stage of the protocol they fixed everything the protocol is secure but um this was some yeah some edge case that we are able to find because we are using fuzzing and invariant testing um as you can We debugged everything back uh um and found the found the root cause with the oiler team as well. Then let's go to a3 for the example of a3 instead of showing like a bug we found we are going to show some of like an example of a big invariant like a global invariant and in this case it be like the a token total supply a uses a tokens for balances. So the a token to token total supply should be equal at least between some deltas to the sum of all user balances. So we have here is we are able to like a helper function like an assertion function where uh we are able to query the state from the protocol from the finguite and then assert uh different stuff the tool will break if it finds uh like if if it makes the protocol go to a state where it breaks everything basically.
So we will get the the call trace back. Um this is another uh interesting step the project I think it's a stealth I don't know yet but he's just mentioning some random um some random u thing or idea or heristic we usually work to lately and is the normally when you set up a finguite the idea is like that you basically deploy everything set up everything set up the oracle prices the initial prices I I mean so you always start from this part and then the fer starts like making random calls the posit withdraw whatever and the protocol is able to reach a different state right this is with the normal version of fuzzing for some kind of protocols like amms and um like little protocols but with uh a lot of complexity on them let's say um or parameter heavy like parameter heavy on the deployment we can also instead of deploying we can randomize the deployment so each time we are going to start from a different point so instead of just looking like that like in actually going to the with on every path we are actually to start from a different initial position. So we are just finding more stuff with this. So I I think it was uh pretty pretty useful when we found this at 4:00 a.m.
probably like working on a protocol and um yeah then some techniques to not use or to avoid using fun uh with fussing clamping and many other many other forbidden techniques overclamping is basically telling the using modmath or like modulus to actually clamp values and not to lose them because for example if I I don't have a thousand tokens and I try to deposit a thousand tokens the call will revert the kid and will just skip to the next call but you can do some clamping stuff that um for example lets you deposit only the amount that you have but then you are obviously like discarding a lot of those parts that were the interesting ones because those are really on the stuff that people don't look into is where the edge cases uh lie at so I really recommend to not clamp just let the um coverage algorithm do the work the path algorithm algorithm do the work over mocking I will show you an example now uh so we can finish over mocking is um a good like a big pain even on like normal tests because people try to mock everything like uh oracles uh balls underlying balls even tokens uh and it's not how real life works. So here if I'm trying to actually make a program simulate the behavior of another program in this case a protocol for example I'm going to try to uh make it as um real as possible in some way. Um so then we have missing coverage but reports people just run the tools and the tools are super complicated in some ways. So they don't actually check coverage. They don't um they don't check coverage or they they check uh different kinds of coverage but not the right one.
So missing coverage is basically you are you the tool is not checking in that place. So you cannot actually check nothing hardcoded value same for uh stable coe assets uh oracle prices you should simulate everything. And then um there's also like a diff uh like a quick uh note here about not using allowances. Normally when you simulate stuff you should use allowances because there's normally there's bucks on allowances that if you for example deposit you can deposit for another user for a two address and you are always depositing to yourself through the finguite you are not reaching that state where I can deposit for another person or I can borrow in on behalf of another person stuff like that. So yeah this was just a quick example about the mocking say for example nowadays like lining protocols are doing like for example for morphobots for example we have like the underlying protocol or for many other protocols and now they are building some kind of yield aggregators or pool aggregators on top of them.
If I were to fast or to build a fasting suite for one of these projects I will um what do you think I will do? I will mock this or uh like the underlying pool or actually do a whole deployment of the protocol on the like at the underlying pool level simulate everything. So you basically the the aggregator protocol the finguite it's twice as big as like the normal protocol suite. I know it's counterintuitive but it's the way um is a way you are able to find those uh rear um rounding errors edge cases etc. And then about hardware and infra you'll be b wondering where do you guys run this uh how can I run it how can I how can I start maybe or many other protocols like asking even clients of us customers of us ask us uh where should we run this I don't want to burn my computer etc.
So um what we say is that um is is like a nice meme now our plans are measured in centuries because we run the I don't know it's like 3 billion runs here the average is like 80k so you know the like the infrar good um so yeah the tools basically require a lot of CPU a lot of RAM and um if you want to do this at scale or in an auditing company for like many customers or actually be able to iterate fast because testing is about iterating fast, being able to uh get the solve everything quickly and not wait for the tool to run or something like that. Uh you need like a go good orchestration um job orchestrator some kind of system for that. Um so yeah we are planning to release uh distributed fuzzing uh really soon release like a job orchestrator for all the works for the customers and maybe we release um the CLI open source I'm not sure can't have can't give details but yeah um basically people were having slow runs because Akina can't I mean it can run on a Mac M2 or something like that or Mac4 but it's going to it's not going to be like three billion calls it's going to be like a million calls uh at the end of the Okay. So, makes no sense. Then fried CPUs.
Um I've uh like meet people running or sweets uh that actually like either the computer burnt or something like that because you just at 100 uh like I don't knowund something uh degrees all the time and then just syncing to a AWS server to some kind of SSH setup is just a pain because uh everything is like super low level in some way like interacting with the UX is not good. So we are just making this UX and orchestration layer on top of it and also making it uh be distributed so nodes can talk with them and actually you can scale horizontally the the infrastructure basically. I think that's uh everything regarding the the Yes. Thank you very much Victor. Round of applause for him.
Please guys, are there any questions? No, no questions. I have a question. All right. Is more CPUs or higher clock speed more important?
Um, it's multi-threaded, super multi-threaded. You can select uh mostly in the tools you can select the number of runners or workers. So the the more CPUs the better basically. All right. Thank you very much.
Now moving on.
Automatic transcript — names and jargon may be misspelled.