Testing smart contracts with Waffle in 2022
ETHCC 5 · July 2022 · 15:33
Bartłomiej Rutkowski demonstrates testing smart contracts with Waffle, focusing on features available in 2022.
Speakers
Topics
From ETHCC 5, hosted by Ethereum France.
Transcript
okay okay yeah it's okay so when it's hello everyone okay I think okay thank you very much uh welcome to my presentation my name is Barta krutkovski on daily basis I work for trufai but other than that I'm as well a contributor to a few open source project of win of which one is uh waffle uh smart contract testing library and today I'd like to tell you a little bit about this so starting with some general ideas we all know that testing is a key to the
smart contract security obviously we have formal verification we have auditing we have manual tests and just like checking everything works but this is these only can be additions and these can only ensure you that everything is fine but this is not something that you can work with on daily basis you need to have a suite of automated tests that are gonna ensure you that everything that you write everything that you code is working on the spot it's not like you can create the whole smart contract system and then like check if it works at the end you need to be sure of each line all the time and in order to have that you need to
you need to switch to the next slide no not this time middle button you can help me well nice so in order to have that you need to have a Swift and lightweight library and that's of vital importance why because if you want to write these tests all the time on daily basis then it needs to be easy to do so it cannot be cumbersome it cannot be inconvenient it cannot be hard to set up you just need to be you just need to do it with a smile on your face you need to do it with pleasure so whenever there is a solidity line of code then there needs to be a test for that and if you're not doing this then
there is a room for improvement um so ideally ideally the slides would be changing on the button click hmm the middle one you say okay no worries so ideally this framework would allow you to work in the test driven development system which probably some of you know this is this idea that you write the test before even coding the logic so you basically write a test that expresses a claim about the logic that you would like to see though the logic
is just not there you see first the failing test and then you write the solidity code or like the actual code to fulfill that logic so as we know the let's say core assumptions or the key needs that that we have around the testing Frameworks I think we can outline two main ideas of how to test solidity smart contracts or general like smart contracts with sort of like native Frameworks so the ones written in solidity like for example Foundry or the ones written in JavaScript or typescript so I'm not going to focus on the solid ones that are brilliant though I still think that typescript and JavaScript testing
Frameworks have some very uh very strong advantages and then still worth considering so uh just to point them out for me they're like far easier to use and far easier to uh to work with on daily basis they're far more flexible because it's super easy to code to create that framework and to add any feature that one would need in the future and they are sort of the app native and what I mean by that is that the way you test the smart contracts is sort of the same thing uh how users then use these smart contracts so it's not only like making some internal assumptions about the state of the smart contract and under
some certain conditions but this is actually deploying smart contracts and actually interacting with them with a JavaScript code so the things that would happen then with like for example the app so that the app interacts with smart contracts performs the transactions checks the state and this is exactly what happens in the typescript or JavaScript testing Suites so now to walk you through the possibilities of the waffle library to see how you can achieve these goals and how um serve the tools that waffle provides help do all that that I talked about so first the setup setup needs to be super super simple
and that's I would say the whole setup so you create a network provider so the objects that allow you to interact with the virtual Json RPC and you create wallets and that's it no further work required then you just need to deploy the smart contract also super easy uh you have deployed contract function out of the box with waffle you just pass the wallet that's going to be a deployer you pass the product of the compilation of solidity and arguments The Constructor and that's it so if you have the setup and the deployment which took in total like I don't know uh less than the lines then you can start testing and here this
is also uh pretty easy and very variable so you can read the line and know exactly what the line is testing you literally expect token balance of the wallet address to equal some number which not only allows you to test the code very easily but also creates sort of a written documentation of the code already um so you can make these basic assertions of any type you can create you can call you can create or perform any read call to the smart contract and then assert the value in any way and what's important it doesn't necessarily need to be quality obviously it can be uh we can expect the number to be larger
than or smaller than but also we can expect it to be within range or close to some value which sounds tricky because we don't want in theory in solidity something to be close to something we want exactly the value that we expect though in some cases if you create your smart contract system based on time not the block numbers you might for example expect that you you you are not sure what the time will exactly be at the time of execution because of the because the timestamp is not like super predictable then you can use the close to dangerous tool but it is there for you and if you feel that it might be used full then just go for it [Music]
and a very cool feature which also addresses sort of that the app Nativity if I can say so of the waffle framework which is testing the events so the events are not that essential for smart contracts themselves many would say because they do not modify the state they probably won't allow to steal any funds this is not a thing that is essential to Smart contact itself but it is still very important for the whole system that is using these smart contracts so for example at the up the apps or some back-end workers or some other tools that interact with smart contracts very often utilize events to sort of source the data about the
transactions about the user activity so on so forth and here you can test that very easily you can just expect the and here actually I would point out to the first argument of the of the emit matcher you point to the exact contractor should emit the particular event so we can for example perform like a transaction that a token transfer but then at the same time you can expect some completely different contract to emit some particular event with some particular arguments which can be quite powerful and these Matrix obviously can be changed so you can expect many contracts to emit many different events in one
transaction if this is something that you want to have and the next thing is testing external calls so we do not only allow you to assert the state or check the events but also you can check whether some certain transaction was performed within the whole call stack of the transaction so here it's like a very very simple example because you like explicitly call balance of and then you expect the balance off to be called which is quite obvious but it applies to internal transactions only so we can check whether your contract was for example correctly executing external calls and whether it's correctly integrated with external systems
and of course you can like pass arguments to that so it's not only checking whether the Cold War was performed but as well if it was performed with um correct arguments and the reverts because obviously not every transaction needs to be successful actually probably most of the transactions should not be successful um and we always have a long set of requirements and restrictions around the main smartphone interactions so we obviously provide you with the ability to test whether the contract reverts properly and it's not only about the reverting the smart contract generally but you can also provide the
exact message that you expect the contract to fail with so you know that the reason that your testing is actually the the thing that you expected it to fail like the the reason is is correct you can use regular expression for that so um so you have like slightly more flexibility around that and you can just be sure that you cover all of the cases and this is a new feature because recently there are custom errors added to solidity so you can also test sort of the the custom part of the error whether the the error was or the revert was emitted with correct arguments
and probably last one of these like matcher type of things which is like a little bit of like syntactic sugar because we also want to make common tests as easy as possible so of course we will not encode each thing as a as a as a matter but for example the thing that is very often checked and is like a very popular test case is whether token balance or ether balance changes after a particular transactions so you'll get that out of the box as well you can test it for a one address or for multiple addresses and obviously if token transfer is super simple example but you can have like a vault dot deposit whatever whatever and
then check whether the balances of the lp tokens changed or whatever else so uh quite quite powerful and looking into some more advanced features rather than just like simple assertions um first would be mock contracts which are super helpful if you are I think if you are somewhere in the middle between unit tests and integration tests because with unit tests obviously you want to test like the internal State changes with integration test you probably want to set up the whole thing you want to set up your system alongside with other D5 protocols and check out whether the interactions are correct so for that you would need to Fork the whole network which you can do with apple as well or
use the test net but sometimes you just want to be sure that your smart contracts react correctly to what other smart contracts do and you can do that by deploying a mock contract that would be a just sort of a puppet but then you can control and program is its methods so the mock contract on a particular method will have a particular endpoint a particular function and we'll just um and we'll just return and the desired the desired value or will revert on the in the desired situation so um here you can see like the whole example so for example you can create a
mock contract and then just perform more complicated checks that depend on external external external smart contracts so here obviously very easy situation but you can for example create a mock for a compound pool for uni swap pair for whatever else and then just very easily check whether your smart contracts are gonna be behaving correctly under different uh different conditions and moving forward fixtures because uh this is this is also a very important one because I started with the comparison or like
I set up this comparison between the solidity tests and typescript tests um okay I'm very close so between the soy test and smartphone and typescript tests so the types within JavaScript are usually not that performant so fixtures allow you to sort of pack some setup for the tests and then perform a snapshot of the whole blockchain and just load the whole snapshot when the test starts so you do not need to redeploy the whole thing or rerun or clean the whole state whenever you want to want a new test you just sort of like return to the state from a particular block and that's it and last final thought is that obviously these features are very cool but a lot
of people for example use hardcat or other Frameworks and just you know want their setup maybe some of this like is interesting but still they want to have their environment as they have it so good news because waffle can be used as a plugin for hard Cuts so most of these features that I described here can be just used with other Frameworks without additional effort um summarizing I will not because in our time but you already heard everything so um thank you very much for your time thank you very much for attending if you have any questions just shoot [Applause] is it working yeah unfortunately we have
not really a lot of time but yeah I guess you can ask at any time just after who so thank you very much