Building secure contracts: How to use fuzzing like a pro
ETHCC 5 · July 2022 · 49:11
Josselin Feist and Natalie Chin demonstrate Echidna for smart-contract fuzzing. The workshop covers invariants, writing security properties and using property-based testing efficiently.
Speakers
Topics
From ETHCC 5, hosted by Ethereum France.
Transcript
okay perfect hi everyone so welcome to this presentation on how to build secure contract and in particular how to further like a pro so who are we my name is justin feist with me is natalie chin so we are both security researcher at 12 bits if you don't know us we are a company where we specialize in high-end security technology we work on blockchain but we also work on other areas we have expertise in cloud native application or in cryptography one thing one thing that makes us different from other companies i think is that we're always trying to apply the latest program analysis technique into our daily job and as a result we have built a lot of tools you might know slitter which is a static analyzer for smart
contract equino we are going to talk about it today tiller which is a static analyzer for argo and smart contract we have also a static analyzer for ko smart contract we have also further for ko so we have a lot of tools that we have built over the years all these two are open source all those two are like free to use but today we are going to focus in particular on fuzzing so we are going to discuss what is fuzzing how to use it efficiently and how to use it in your daily job at the end of the presentation the goal is going to be for you to have some intuition on how to apply something in your daily job as a developer or as an editor you can find the slide of the presentation here right now it's on the
pull request and soon it's going to be on on the master branch so 12 bits publication it's simple okay the first question we're going to ask ourselves is how to find bugs let's say you have this piece of code so you have like 10 lines of code more or less what what this code does is that it allows anyone to buy some token it has a function a public function to buy and it has some function that is going to check that you are providing enough ether you don't need to spend too much time on this you don't need to try to understand it the question is more you are giving this piece of code what can you do to check if there is a bug what can you do to check if there is something wrong going on here basically you have four techniques at
your arsenal the first one is unit test i'm assuming everyone is aware of how unique test works you can do manual analysis you can do fully automated analysis and you can do semi-automated analysis the first one you need test you basically create a test cache that you to check like some specific value of your system unit tests are good and you should use unit tests but usually you're going to cover like the happy paths like the paths that are going to lead to good behavior you are going most likely to miss all the care that can lead to vulnerability or critical issue we actually have data from our past experience with working with clients that shows that there is no correlation between having good unit tests and the likelihood of having a
high severity issue in the code base which is an interesting result just an example of unit test nothing new here the second technique that you can use is manual review so you can go line by and line in your piece of code and try to see if there is something wrong try to see if something can be abused by an attacker this is difficult this is time consuming and it's going to require some specific skills so you need to understand how to think as an attacker you need to be aware of all the class of possible bugs that can happen in the code base usually to do manual review you're going to you know ask security fields such as tradeoff bits or other to perform this type of analysis mostly because as i mentioned it's time consuming and it requires like a specific set of
skills the next technique that you can use to catch some of the bug are fully automated analysis so here you have a tool you're going to run the tool on your program and you're going to try to see if there is a box for example there is slitter that is going to catch the most common type of issue like queer and transient and stuff like that it's really good to catch some specific type of bug it's really good to to kind of catch the common type of bugs but it's not going to be able to find more like scepterbug more bug related to the logic of the system here you have an example of slitter so stutter is a static analyzer and we have integration with the github code scanning page such as as a developer you can add it for free in your workflow and
every time you do a commit every time you do a pull request the card is going to try to find like the most common vulnerability we entrancy and check call and so on the last class of of techniques that you can use is called semi-automated analysis so here you are going to use a tool to check if there is a bug in your system but instead of looking for command vulnerability you are going to help the tool to provide some form of specification of what your card is supposed to do and here you're going to look for bug related to the logic or bug related to the more in-depth you know application of what you're trying to do one technique is called property-based testing and with akina and it's what we're going to talk about today
yep so i'm going to go into property-based testing what it is and particularly what it is in relation to echidna so basically from echidna's point of view when you're fuzzing you're essentially it would be like you were typing on a keyboard trying to throw random inputs at your smart contract what happens when you call a certain function with inputs that aren't expected what happens unlike unit testing unit testing you're specifying maybe a certain variable or a certain number with fuzzing you're essentially going to be tapping at the keyboard except that it's all within the fuzzer so fuzzing is pretty well established within traditional security software and
for a lot of the times these secu these fuzzers when they're used in in those contexts are checking whether a contract or whether a code base would crash our crash is possible within this context that you're running it in but smart contracts don't really have crashes so with echidna we're not going to be looking for smart contract crashes we're looking for we're thinking of this at on a different angle and thinking what are properties that you want to hold true within the code base and from a developer standpoint you know what what needs to be true in a code base it's basically like unit testing on steroids so to start with what is actually
required in order to do invariant testing well you need to know what invariant is you need to know in terms of your code base and it's going to change for every code base what needs to be what needs to hold true and echidna this is where echidna comes in because we're going to be able to call these smart contracts with these and with defined invariants and we often use these in audits and we see this used in very mature code bases so this isn't a replacement for unit testing this is you have unit testing and you have fuzzing so you can get the duality so one example
is for example is when you have a token one invariant would be that a user balance should never exceed total supply if it ever does exceed total supply then you know there's a bug somewhere in your smart contract maybe it's arithmetic maybe it's likely it's arithmetic but access controls for example once you have that property then you need to actually convert that into code so this specific example is we're defining a function called echidna balance of total supply and what echidna is going to do is look for all the functions that are prefixed with echidna and specifically ones that return
the boolean and it'll essentially determine whether there might be scenarios in which the the value of the balance of the sender is less than equal to total supply so this looks very similar to what you might write in a unit test except in this specific case akin is now going to generate and call the smart contract from a series of different addresses to see whether it whether this invariant may break so from an echidna standpoint unlike unit testing where you need to specify um what are the incoming arguments with echidna we have this smart contract code and for this example it's really just an
erc20 token this is a simplified example of course it has in this example total supply balances and a transfer function and the invariant that we're specifying is that the balance of the message.sender is less than equal to total supply so from a kidney standpoint it's going to determine throwing random inputs within message.sender and calling different functions like the transfer function is it possible that this invariant ever breaks so this requires a bit of a paradigm shift compared to unit testing because we need to think about in terms of this entire system architecture what is required of the system in order
for it not to break so for this example this is the transfer function it's essentially going to decrease the balance of the message.sender and then increase the balance of two it's from the inputs it's going to get the two address as well as the value and when we put this through echidna with the property we can define this test token as an as inheritance through using the token contract and from when we initialize this contract it's going to be initialized so that the echidna caller which is the contract
address that's going to be calling this contract gets started with an initial balance so once we actually define these echidna tests the we can now define this property as using echidna to test the balance making sure that the balance is now less than or equal to their initial balance so once we've run echidna it's going to now determine that if we transfer to if we call the transfer function with the zero address and a value of one this specific input set is going to now break this invariant
so from a triage point of view echidna will provide all of the inputs that are required to break this invariant now that requires so this is a very simplified example a token contract is one that's relatively easy to reason about because the standards are defined the variables are defined we know exactly what's expected to happen in a token contract now that raises a really good question of what are invariants within more complex code bases and how do we actually start thinking about invariance in terms of larger contracts and larger and more complex contracts
so to start with in order to even find invariants and start finding them we need to start small and start iterating over what are possible in variants that we can now build on top of so from and from a developer standpoint and from our experience on on audits as well is defining in a certain piece of code what is expected what is the code expected to do and this is the the baseline that we need to know what the code does in order to even define what property should be holding true once we get that and we can get that through documentation through talking to developers understanding use cases
understanding the context in which functions or contracts are used then we can actually start running them and writing them into solidity and this process is much easier said than done because we need to also make sure that echidna isn't going to specifically choose it's going to essentially it's like the cat on the keyboard it's just going to randomly generate these inputs and so we need to be very careful with what are your preconditions that you want to specify in terms of if a variant is actually going to hold defining all your preconditions and post conditions and then finally running echidna so if these invariants are actually broken
an echidna finds a test property that essentially that fails then that's where the manual investigation you need to go in you need to determine why is it failing is it because your invariant was wrong and that that requires a whole level of discussion of is it contract is it something that's within your contract or is it something that's within your system architecture um or is it in the translation between between the invariant from english into code so to start with you really need to sit and think about what your contract is actually supposed to do you need to
really determine from the experience of really combining the experience of project teams who are building the code and really understanding expectations the easiest way that i've found is really to just write down what the invariant is what what is expected of the system in english and then you can start to really change and convert that into code so as an example um math math libraries are one that's easier to reason about because you there are expectations that you expect math libraries to hold for
example 1 plus 2 is always equal to 2 plus 1. if this if any of these properties don't actually hold then you know that there's a bug in your smart contract in the same way that you can test a math library then you can test other libraries in the same way and bringing back to going back to the token example as well one example for total supply is that no user should ever have a balance that exceeds total supply that goes back to if this is ever possible then there is a bug in this contract and we can also start to reason about what are the expectations for other
functions as well for example if you're transferring tokens to another user you always expect that the sender's balance is going to decrease and that the receiver's balance going to increase if there are any changes and that doesn't actually hold then we know that there's something wrong within that token contract and similarly we we can reason about we can reason about expectations of what would happen if you don't actually have enough funds if you have insufficient funds then you should never be able to transfer balance if that is ever possible within a token contract then you know there's also a bug once you get into understanding what are
the expectations from the high level point of view then you can really start to think about how would you actually test this in practice how would you write the echidna properties in order to really be able to determine whether you use a kidney to determine whether it's exploitable so there's really two two different uh two different methods to do this one is a function level invariant and this is going back to the example with the expectations for arithmetic and this is stateless so you can essentially you can get echidna to for example call a contract that adds two numbers
and then adds the um same two numbers in the different order and just making sure that they're equivalent the other system level and variant is going back to what would happen if if you're using a kidney to test something like total supply so for function level and invariance it's always going to be inheriting the target the we're going to be creating the test function that essentially wraps um the contract or the function that we want to test and then we're using assertion statement just to make sure that they're actually equivalent so this is this is this
specific echidna test is essentially going ed kidnap is now going to generate random values for this these two uints um and any property in which or any set of values in which this assert statement is false echidna would raise an error the other type of echidna usage is through system level invariance and this is there's a there's two different ways to do it one is if you have a relatively simpler setup within within these contracts that you can you can you actually just use like a kidnap to deploy deploy the entire system this would mean
that pretty much any time you're iterating over your code then you can run the contract and deploy the new version within your constructor and echidna what it will do is be able to explore all of your publicly available functions and determine whether there are s like variations of functions that it can call in order to break the invariance that you've set the other option is especially in this is especially true of very complex code bases that have many contracts that work together you can also use either your unit test framework or your deployment scripts to deploy the set of contracts on
essentially a local version of your blockchain and then echidna can start to fuzz on top of that so if you have a very complex setup then you can essentially run your deployments get it running on atheno um and if echidna will start to generate transactions on top um of of the code of the state of the blockchain after those deployments have been run so for this specific example um this is a system level invariant and echidna's essential this is a very similar example um to the previous and basically it's going to echidna is going to determine whether there are any cases in which
this assertion will fail before i go further is there any questions when you generate the input is it really pure random input and if yes how do you get sufficient coverage that's a really good question so it's not purely random akina is going to kind of collect the value at runtimes and it's going to use them from time to time and they're also some heuristic like it's going to favor hks 0 1 2 max huey and max
minus 1 minus 2 and so on so it's more or less random but there is some some kind of smart heuristic in it do you analyze the code in advance do you extract the constant from the code yeah exactly we actually use liter static analyzer to extract the constant extract a couple of arithmetics operations and we feed this to the further and what was the second question from more of like a devops perspective do you guys plan to essentially enable this to be triggered through like something
like github actions and then you guys have your own infrastructure with ganache or whatever you guys are using to then kind of facilitate the automatic deployment of contracts uh against the test net so um technically it runs on its own version of the vm so there is like a local kind of blockchain and we have a github action for it so you can configure it and just let it run on github action there's discussion on how much time you want the further to run you can let it run for like 10 minutes you can let it run for two days for two days is not going to work well with github action so it depends on your setup well actually the tool is free so
okay oh the fuzzing itself is another bike but for the like to get the constant before fuzzing it's another source code yes but then we run lack of code pair-up code okay so really their approach is to start simple you think about the invariant in english you convert them into solidity and you iterate now the question is where to start which function to start should you focus on
the contract so you focus on multiple functions should you like you know explore different approach and when you have the code base you don't know where the bugs are right otherwise you will not do that so you have like a code base you don't know where are the bugs you basically have to approach the first one is coverage based where you are trying to cover as many functions as possible not necessarily in depth but just to cover as many different behavior from the system the second approach is to go and focus on one or two components and go in desk going index in the center of trying to write as many invalid as possible for these specific components and you can iterate you can start by spending maybe one day as a code
coverage you're going to try to cover as many functions as possible with really simple invariant after one day you you you when you have some you know intuition and some understanding of the system you can focus on a specific component maybe a math library maybe some some bookkeeping maybe something a bit more complex and you go in this you're trying to kind of write as many invariant for this specific function or component as you can think at some point you will be to a position where you don't have any idea anymore or you are writing invariants that are exactly the same and you are not progressing then you can just switch back and go back and forth like this there is no you know right and wrong approach is really a matter of building your own experience bringing your own expertise and based on your intuition
with respect to understanding of the code base obviously something which is really important and we're going to repeat it again and again start simple if the first invariant that you are writing leads to a bug there is something wrong in your process basically like the first 10 15 invariants that you are going to write should not lead to any bug because they should be simple and they should kind of highlight really things that should already be true within the code base by starting sample uh it's going to help you to have a better understanding of how to write the further avoid property rather further maybe start having some kind of initialization maybe more complex system invariant and you can build on top of
that once you have really simple invariant you can start to think about composition you can start to think about function relation other functions that should be more or less the same we took the example of the token if you have a transfer and a transfer form if you call transfer form where the form is the sender itself should they behave the same yes no is transfer additive like additive like in the sense that if i want to transfer 20 token can i do two calls to transfer with 10 and 10 should it be of the same should both like execution be equivalent spoiler no i won't explain why it's not equivalent
i will let you think about it but going through this exercise of trying to understand the expected behavior of the system and what should be true and what should not be true um it's kind of a process that you are going to go through and it's going to help you as you are going we're going to build your expertise on this and yeah from from our experience even if you don't use a kidney at all if you just stay uh at the english level and just write your invariant as like a list of 20 30 40 things that the system should do it will already help you it's already going to be a huge step forward with respect to the maturity of your code base if you use akina or any other tool it's going to be even better but just by starting by thinking about invariant and having
this shift in the paradigm in the way you are building contract is going to help you a lot and actually doing audits sometimes where we are like okay what the system is supposed to do like what what are the environment just by writing some invariants we realize that some are obviously wrong and broken even before running a kinder so this is really like a powerful tool uh in the way we are kind of thinking about the code base okay if we take back the first example so again here i have a function that can buy it can buy 10 token per one ether and you have a function that is going to check if you provide enough it with respect to the number of token you want to buy
you have two functions the first one by is steadfall it's going to mean something so you have like the state of the function of the contract that is going to change the second one is stateless it's just taking some parameter and if everything goes wrong it just returns so here you can start with the second one it's easier you don't have to do any initialization you don't have to mint any token and you can just focus on that what invariant so here the function basically takes some token take some amount of heater do some computation and try to see if you provide enough money one invariant here is that if you provide zero ether
the second parameter must be zero otherwise it means that you can provide uh i want to buy one token 10 token 100 token and if i provide zero data this should reverse otherwise you get token for free basically something which is interesting here that this is an invariant but you can write it without even understanding what's the arithmetics here like here that metric is simple but you could have like really complex formula you could have like things related to you know uniform or like a complex arithmetic you don't even need to understand it you can just by thinking about how this function should be if you can write in variants here's an example of invariant so i am checking that the number of token i want to receive is
above zero i'm calling this function and here i provide zero to the second parameter so i'm calling this function by saying the number of token i want to have is above zero but i'm providing zero heater and here i'm just saying that asset fault because this should never be twitch this function reverts so basically if during the execution i can reach this path the environment is broken i i've done something that should not have happened and if you run this with a kidnap it's going to say oh i managed to break this invariant and i call the function with one why is that um do you have any idea yeah exactly like here
you are doing the number of tokens divided by 10 because you want to buy pair one enter 10 token and if you ask to build automint less than 10 this is going to run to zero and you basically get the token for free so here again you write an invariant you don't even think about the formula you don't even think about what it does and you manage to find a box which is pretty nice i think any question okay let's talk about other tools so equino is not the only tool that allows
us to do semi-automated analysis there are a couple of additional further are there there is one in dub one in bernie one in foundry their framework might be easier to use on the first step they might allow you to quickly add some simple tests with fuzzing because they are within the compilation framework so you might be more used to it however they are not as powerful as a key now we have been working on akin now for i think five years now and we have been using it in countless offered it we are using it basically in two-thirds a three-third of our audit so yeah they're not going to have the same number of features not going to be as smart in the exploration the second kind of categories of
techniques that use semi-automated analysis are formal method-based approach so you have montic kvm certainly and so on this technique are going to be more or less the same idea like the user is going to define an invariant the user is going to define like the specification of the contract and the tool is going to use thermal method to check if the invariant old this technique have one kind of benefit over fuzzing is that they can give you quarantine they can give you proof that the bug is there or not however in practice all these tools are difficult to use they require some specific knowledge they require like years of expertise and program analysis to use them correctly so basically like if you have one week
like you are developing your system and you want to spend one week to improve the confidence of your code base the amount of kind of confidence you are going to gain by using fuzzing uh in comparison to using one of this technique is just not going to be on the same scale like to use this technique if you have like months you will be able to use them if you have one week you won't be able uh this is a a quote from the ceo of runtime verification so the people building kvm is basically saying that if you want to use formal methods to check and to verify your contract you need to have nine times the resource for development and this is from the from the team building this this you know tool so as a
developer it might even be like you know significantly higher so they're nice to use but they are really costly okay now the couple of unique advantage i think we have a couple of additional features that are not there in most of the other tools for example equinox can give you a summary of gas consumption using fuzzing so basically just going to call all the function randomly is going to give you an idea of what are the transactions that consume the most cars if you are looking to kind of tune with optimization of your system and you want to find some hks if you want to find some place where running the code might be really costly and you haven't think about it using
fuzzing is like a nice uh kind of way of doing it it can do differential phasing so differential phasing is basically the same idea but instead of comparing your properties you are going to compare two implementation of the same same things for example if you have two contract version one and version two and version two is just a refactoring of your code base but it should be the same you can use differential fuzzing to actually check that they are the same it works with any compilation framework or dart truffle brownie foundry whatever you are using a kindr will work on top of it we have different apis in the example we saw a couple of examples where using the pro the boolean property where you're defining
properties and the function should return a boolean or assertion you define with an asset there is another mod for using with that test and front remote which is slightly different but more or less the same idea again it's free and open source so you can just use it and there is no limitation okay so today we saw akin now which is a smart contract further if you want to learn more about it we actually have tutorial in building secure contracts in this repository you will find a lot of additional guidelines on how to you know improve the quality of your of your code base not just for fuzzing but using additional tools and additional guidance
for example we have a token integration checklist if you want to integrate with arbitrary token what are the things you should be aware of we're getting a key now again start simple try to write invariants that you know are not going to lead to to any issue but they are going to help you to build on top of it and they are going to help you to have like an iterative approach start with english then solidity and kinder and you know loop about it also we are hiring so we are hiring both security consultant and apprentice so we have an apprenticeship program which is a three-month program where we train people to become a auditor and the company we have been running the program for more than a year now and we ended up
hiring everyone so if you are interested in this topic let me know final word your mission after this after this presentation is to try equina either on one of your code base on some of the code you have and let us know how it goes let us know how writing invariant goes and let us know what's the difficult part and what you know we could improve to make your life easier any question so i'd like to hear your approach about how do you write invariants um as i see there are two ways either which is interface based or implementation based so on the first approach you can just
look in the interface without implementation and think for yourself what the properties should be and the other one is just when you just focus on the implementation itself and then you restrict yourself to what the function actually does so what is your approach on that that's a really good question i think it goes back to having an approach code coverage or behavior coverage like the interface is going to be a bit more code coverage where you don't necessarily go in depth into what the system is supposed to do you're just taking as like a black box this is what you're supposed to do let's write an invariant then you can go one step further and really try to understand the actual uh you know behavior of the system's actual i don't know if you have like a five
line of arithmetics what this arithmetic are doing what they should be leading to and then you go and go a bit more in depth so again it's really a matter of going back and forth between both approaches sometimes you want to just go briefly over the different interface and sometimes you want to go like in this both are important and it's going to depend off your code base and your approach and your understanding of it yeah i just want to add quickly sometimes it's useful to look at the interface first because then you can start talking to your developers and just making sure that those assumptions that you have on your interface are correct first until you start digging deeper into the
implementation and then just making sure that your your high level assumptions are correct first so sometimes it it we do often bounce between the two and i think that's probably the best best use of time because then we can also there are cases in which you might look at invariant and say yes this is this looks correct but once you really start thinking about how is it being used in a system and getting that context that it's actually correct but with more preconditions than you initially thought and it's kind of like thinking about fuzzing as unit tests on steroids when you're going to build your knee test it's the same are you going to just build like you know regression test are
you going to be unit test is going to depend on your approach configuration you have like the test limit okay that's a really good question so the question is about the configuration of a kiln when you run a keynote you can configure some stuff and there is two parameter one parameter is the number of
uh tests you want to do like number of uh input you want to generate do you want to test like if you have a function you want to test a function with 10 100 1 million input before like the before i can stop the second parameter is the sequence length this is only important for system and variant the seconds length is going to be when you start a cleaner you are at second zero ikina is going to make multiple transactions one two three four whatever is going to go in depth into into the program at some point it's going to reset so the sequence length is basically yeah it's basically the number of call before akina with it
for the number itself answer is it depends if you are looking at function invariant the sequence length can be like one basically because you don't care if it reset it's going to be a bit slower if you put it too small because uh because of internals like when you visit a blockchain yeah you have some some variables that you have to to do with that for the first parameters the number of tests you want to do this really depends on how much confidence you want to have about the code base so i don't have like a concrete answer for that but it's basically going to depend on the budget you want to put in the exploration do you want it to run it for one hour do you want to write it for two days um that's basically it yeah like for for like we sometimes we
run it for like uh like a weekend or something like that we have a second repo it's called yeah it should come back hopefully yeah we have we have another repo it's called echina powered and basically what it does it's also open source it's going to parallelize a key now ends so that you can run it on you know on the cloud basically and you can run it with multiple processor and it's going to share the input generation so if you have like a large machine with a lot of you know processor a lot of memory you can also not run it over like two days you can run it over five hours but in parallel
um uh how can you like control the fuzzing um domain range so that say you want to test only numbers under like 100k because that would potentially um [Music] accelerate the the process that's a really good question so how can we kind of help the further to not explore any value and only focus on specific one the really simple way of doing it is to add precondition like like here you say it should be greater than zero however this is not the best approach because the further is still going to generate
input here it's just zero so there's just one value that is going to be rejected but let's say if you want to have this value between i know 20 and 25 one way to do this is to use modulo so in building secure contract you will find kind of pattern and tips to implement that but basically the idea is that here you could write this where the number of token you want is equal to the input and you use modulo to create a range between the value it will make more sense with the example but it's like a a programming pattern to reduce serve and show the value like
basically cleaner is going to generate any urine and locally you can weight yourself that makes sense and the corollary like is it possible to run akina on a wide range but don't let it fail on the first failing assertion like you let it compute all the successful and failed sets and you could like some somehow draw a conclusion on what kind of values it just failed for um so you mean like if you have multiple accession and you want to i don't want akina to like fail on the first assertion i just wanted to run compute the whole thing and just uh
analyze the data set that at the end that's a good question i don't think we can do that out of the box so you can probably tweak by commenting the set and and stuff like that we have a corpus we use uh in akina so if you want it without any accession it's going to generate a corpus of inputs or all the inputs to explore that that you use to explore and then you can reuse this by adding a session so it's not out of the box but kind of that makes sense complex large complex
code base with multiple contracts and stateful uh invariants like do you have any tips to like get there on very specific scenarios like when there's a lot of contracts a lot of states and so on so we have this additional tool as i mentioned we have a lot of tools uh where is it yeah i don't remember where is it in the slide but it's called etino and basically it's a tool that is going to allow you to run your unit test and seed the fuzzing with unit test so if you have a unit test that calls five different contracts first
akina can reuse this information and start the fuzzing after it so if you want to like yeah if you have a complex system you need to have like a lot of different initialization maybe you you need to want to do a couple of first swap or you know we want to do something like that uh we can but it's a bit more complex but we can use it you know is this compatible with foundry or any kind of test or oh it's compatible with any tests that can run with ganache so if it's not compatible with foundry we can probably add it pretty quickly so
so the question is regarding if we can support main and fork not directly because the issue is that basically akina is going to create his own virtual machine you have to re repeat the transaction from mainnet to see it like you cannot connect directly to like a like an entry point or something like that it's something we are working on that's a bit more difficult if you can replay but what we need is a transaction in ganache so it's not like the initial state of
ganache it's really like the transaction sent together so we can reply anything we can see as transaction but we cannot take any initial state at the moment does do you have any way to fuzz into it without well well with this static analysis okay so we do support out of the box multiple contracts uh if you have the source code uh we can just like if like if here you have like an external call and the contract is deployed akina is going to work out of the box like we it cannot support multiple contracts
and it's it's needed for like system environment because like any any like common contract is going to a system is going to have multiple contracts um yeah and just i guess it's a bit of a follow-up to a previous question um with the um testing when you have a bunch of inputs and it creates an error like a thousand assert or something you found like you've broken an invariant um it it will then um like change the inputs and do it again or does the testing sort of stop there oh i just yeah so this is a technique which is called shrinking because basically like let's say it now found um a set of transactions to
break the environment but maybe a lot of transactions within this set are useless maybe just you know call randomly some function and everything so once enough is fine like fund an environment which is broken with a set of transaction is going to try to reduce the transaction size so that you have kind of a meaningful call and then it continues anything else and then you just get a report at the end of all that yeah okay yes and you have like a a live report with respect with with like the clean interface like yeah i think i have like a screenshot yeah okay black yeah it's the end but uh
it's raining but you don't actually change the state where you just like like so if you just have like if you send like within your unit test or deployment a weed function uh which transaction is still going to use it to seed uh the information so it's still useful you basically just need transaction input and if the transaction does nothing change nothing it might
still be valuable for the further because maybe you are calling like a getter with i don't know an index or value whatever and this might be useful to explore later on some pass thank you okay any additional question who is going to try a kid now okay yeah and if you have any questions we
are here for the for the week so don't hesitate to bring us [Applause] you