Wake Framework: All-in-One Toolkit for Solidity Development

EthPrague 2024 · 2 Jun 2024 · 24:51

Michal Převrátil, who leads Ethereum tooling development at Ackee Blockchain Security, presents Wake, an open-source Python framework for deploying, testing and analysing Solidity smart contracts. He walks through unit tests, fuzzing, fork testing and cross-chain testing with coverage shown in VS Code, then covers static analysis detectors and printers and the language server behind the Tools for Solidity extension. His examples include vulnerabilities Wake helped find in real audits.

Speakers

Topics

From EthPrague 2024, hosted by ETHPrague.

Transcript

[Music] [Applause] hello everyone I hope you enjoy like this event and Conference even through this unfortunate weather so as it has been said my name is m clicker yeah my name is Mel and I'm the lead developer of tooling for ethereum at e blockchain security we are smart contract Auditors mainly for focusing on audits made on ethereum and sonana but we are also tooling developers we love building open source tools and we have two tools to share with the community wake this talk is all about wake so I'm going to skip

it for now and then there's Trident which is fuzzing solution for salana we also onboard new developers to the ecosystem for example we run School of salana uh we are excited to work with the best of the best clients out there like for example Axel safe Lio of one inch and we've received a couple of grants for example and the Grant from coinbase started the development of wake but let's get to wake so what really is Wake it's it's an open source tool it's a python based tool but it's not only a tool it's a framework it's a framework for deployment and testing so anyone can deploy any contracts to many chains that

we support for example we support B&B chain polygon or for example BAS but there's also the testing part so that we have SIMPLE unit test anyone can try to debug or test a simple case in their contract there's also support for fuzzing which is quite different technique when someone generates random data generates random sequences of operations and passes these data and the sequences to contracts trying to break the contract and trying to find some interesting boxs there's also support for integration testing this is mainly useful for projects that have some dependencies for example chain link or AA or some projects like this and in this case we can Fork any chain we want

to probably domain net and we can just use these contracts normally as if there were on our deployment chain and yeah so this is the testing and deployment part there's also static analysis framework and I believe there are two main like outputs for users from static analysis and these are detect and printers so detectors are mainly about finding some common issues some vulnerabilities or code quality problems in code this is quite clear I believe and the second feature is printers that are basically like almost the same from the developer perspective but very different from the point of view of the end user because

printer extract some inter information from the source code they don't Pro they don't just show some let's say um findings or problems in Code by they but they just print information from code and finally there's also language server so let's say that we are developers we want to develop Some solid smart contracts we want to use vs code but the problem is that vs codes itself doesn't support uh solidity so we have to use a few of extensions that are out there one of them is called tools for solidity and this extensions is also uh developed by e and it works with Wes so every single request that is made to the extension

like the code highlighting going going through references or uh renaming a symbol everything goes through vake so vake is like really behind all this stuff and tools for solidity is just a front end for vake uh vake helps us a lot in our Audits and this is an incomplete table of all the findings that uh were found thanks to wake some of them were found using State static analysis which means with detectors this is the case of the first one that ERC 4337 detection this is like account obstruction and the problem here was like incorrect uh storage to access uh uh storage exess I'm going to talk about this one later

in the presentation some other findings are from fuzzing that's the example of uh the the finding from Lio or for example from axar While others are from simple unit test this is the case of soid so but let's move to to the first topic which is deployment and testing and I believe the best way to introduce a testing framework is to show it on very simple example that everyone can understand so I've got a very nice C example here what we are doing here is that we do some imports that are quite necessary for our testing then we import from P types P types are very special to W because let's say that we we have some sol code base we have some contracts

here some structs some events and so on but we want to have these same types but in Python so we have Auto completions and type checking support and what w does is that compiles the project it generates P types which are like types from solidity but in Python this way this way we can import them and then we have Auto comps and all the nice stuff in Python uh let's move back to the to to the test so we are connecting to a chain in this case we are using Fork testing so we are forking from a local node running at Port 8545 so we are expecting uh an ethereum mainnet Noe here and then we have a test we are generating two random addresses the

first one is for sender the second one is for recipient after that we can just typ cast and address of usdt to erc20 because we are using Fork testing so the token is already available here after that we can make some assertions about the symbol about the name about the decimals and now since we are in testing environment we can do anything we want to so we can use some cheat cheat codes to Mint some tokens 200 tokens to the cender after that we can transfer a half to the recipient and finally make some assertions about the balances of those senders and recipients let's talk about some more

interesting features in the testing framework as I said we do support fuzzing which is generating random data generating random operations and passing those data and executing those operations on contract there support for fork testing as I showed in the previous example and let's say that we have a transaction that we interacts with many contracts and some of those contracts are from the fork environment and in this case we want to print a cult race which shows all the contracts that were executed or like yeah basically executed in a transaction and this C just shows the names of the contracts of functions of parameters and so on and because of this inter itcan integration we can we

can show the names of those contracts because vake basically fetches like the source code and the API from ether scan so it works even for the fork contract then there's also coverage analysis support so we can run a testing suit using coverage uh code coverage feature and we see the results right in vs code is highly integrated into vs code so we are trying to use the best of Two Worlds like the command line and vs code so the coverage collected from fuzzing and testing is showed in vs code and actually in the case of fuzzing and the the coverage is showed in real time so as we fuz new coverage lines appear or are are highlighted in vs code there's so Al also support for

cross chain testing so we can Define any number of chains most probably just one or two of them and then we can when we are deploying new contract we can choose a chain we want to deploy to so this way we can uh test very interesting projects that need cross chain testing or just they are using multiple chains and this is very very nice feature needed for for cross chain projects there's also or there are also random seeds this is especially useful in case of fuzzing so let's say we have found a very very interesting issue but we need to print some information about that issue some Lo locks and we need to run the same test case again again and again and this is possible because of

random seats because we are basically after every single run of vake test we print the random seat and then we can use that random seat to reproduce all the same transactions inside that teston and finally does there support for Marly processing which means that we can execute uh like a single test multiple times at multiple CPU course or multiple tests uh like spread or split across different CPU course so we can speed up the whole execution and there's also debugging since we are writing tests in Python we have very strong debugging capabilities we can stop at any any line in the code

we can print any information about code and we can also interact with some contracts that are deployed or we can even deploy a new contract I have quite nice animation on the next slide this is an example and unfortunately it doesn't work so I'm sorry the animation won't be here but we can as I said we can stop at any line and we can print anything about the contract and yeah we can even deploy new construct you can print call traces so the debugging is very powerful in the testing frame framework so and since we are testing in Python we can use something called differential testing and the this is all about that we have

some solidity solidity code and then since we are doing testing in Python we can reimplement the same problem but in a different way in Python so that we can compare these two models the original solid one and the new python one and sometimes it's even possible to reimplement the same problem in a different way and this is the case especially since we are working in solidity we are somehow limited by the gas we are also limited by mappings we cannot iterate over mappings while in Python we can iterate over dictionaries so we can reimplement the same idea the same problem but in a different way and then compare these two results that are often very different at least from our

experience from auditing this is an example from IPO like the project that we have audited we are trying to compute some interest it's a floating interest so we are multiplying multiple values like from in from intervals and this is something that cannot be done in contract it will be super gas expensive to do so so they are using different approach but in Python we could just multiply these two values as as is as is as the formula States because we can there's no reason we couldn't and at the same time python supports floats like floating Point numbers so we have more precise results than the sled implementation and we can probably find some errors and then decide if the error

is big enough or or just small now let's talk about performance of course we want to find box but we want to find them very fast and yeah so we took Unis V3 core repository we took 271 tests that were already written in hardhead which means in JavaScript and we have reimplemented those tests into brownie into ape and into wake and these are the results so these are the times in seconds and this is the time of executing executing all the tests like 271 tests as and as you can see they managed to run all the test in less than

4 seconds which is pretty awesome in my opinion and that's because of bake is highly optimized for Anvil Anvil is part of the founder project so it's written in rust and it's very fast so V is somehow integrating anal and we are trying to even improve this numbers by integrating more libraries and code to make the the execution even faster all right so let's talk about static analysis now as I said static analysis is mainly about detectors and printers I'm going to start with detectors our approach here is that we prefer pre prefer quality over quantity so we don't want to have 101 detectors

trying to detect everything we we possibly can but we are slowly it seems like yeah we are here nice uh so we are trying to uh slowly build one Detector by one while keeping the high quality at the same time we do care about user experience so of course we have we have some command line input which is very nice I'm going to show on the next next slide but except from that we have integration GitHub integration so when someone pushes new comment to the to the GitHub repository uh there's automatic compilation and in the pipeline then all

the detectors that are that are available are run automatically and the results from those detectors are are showed in a very special like page on GitHub that is only ACC uh accessible for owners of the repositories so it's not possible that that the finding would would leak to someone who's not the owner of the repository there as I said V is highly integrated into uh into vs code and so there's extension for vs code and there's automatic compilation over each change to the code base so every time sometimes type as someone types some new code in vs code there's automatic compilation and automatic run of detector

and those detections are showed in real time in vs code and of course static analysis May provide sometimes false positives and in this case we can just Tye very single very simple uh very simple like comments in code that disable very specific finding or maybe like a range of findings across across the codebase and finally we do have public apis so everyone can create their own detectors as I promised we'll speak about that ERC 4337 Detector by the way this is an example of a command line

interface so I believe it's very user friendly it shows all the like the specific line where where the issue is also some lines before and after uh there's confidence and like severity of a finding and there's also like uh text message describing the finding but let's talk about that ERC 4357 detector and basically that ERC defines some rules for smart accounts there has to be a function called validate user operation and there's there are some restrictions for the function they the function cannot execute any like it it there are some restricted restricted of codes

inside the function so the function itself and the functions called from the function cannot uh use for example time stamp and so on and there are also some restrictions for storage access not for the smart account itself but for contract that inter like interact with the smart account and this detector does that it checks those invalid up codes that cannot be used as well as the storage access so this is something automatically reported and honestly for me as an auditor it's very hard to find those storage accesses because the code can be very very comple complex and finding these is is non trous so I'm really glad that we have such an detector when it comes to Performance of

detectors we don't usually care about execution times we care mainly about false positives and false negatives so we've taken one single detector in this case it's right after right so we are writing a single value into a variable and then we are writing maybe a different maybe a same value to the same variable but we didn't use the previous previous Li and values so the the first V was basically useless and we've taken three different metrics the first one is precision which states like the number of good findings versus the number of all findings reported from the detector the second one is recall the recall is like non missed right like so so

basically it says how many findings we did not miss versus the total number of findings out there and finally this there's F1 score which is basically like a combination of these two so it's like a harmonic mean between recall and precision and I believe the table just says it for itself the det is very very very good and it's also one we are glad to use in our auditing process okay now let's talk about printers so printers are used for data extraction they extract some information from the source code it can be for example graphs so yeah so it can be an

inheritance graph like graph on inheritance of contract it can also be like for example cross reference graph showing how contracts interact with with each other but it can also be something like AI storage layout or S some statistics like lines of code or for example number of functions there's also integration for language server I think this will be the best describe on an example so I'm going to just skip it for now and finally there's of course public API for creating custom printers this is an example of a commandline printer like a static printer we've got an interchange token

here like a contract and we are printing storage layout of that contract so as you can see there are some storage variables there are names of those variables there are types and and since uh the contract inherits from other contracts we can also see like the name of the contract that Define that specific variable and finally this is an example of language server integration so this is a printer but for vs code and what we are trying to do here uh we have a contract and we want to show to the end user public and external functions from the codebase from a single contract so basically it's about extracting information from source code but we want to show it in like vs code native way so

not not on common line but in vs code and yeah so we have a contract named stonks here and there are some labels above the contract one of them is public functions and if we click on that label we can see all the public functions that are defined inside the contract even across inheritance this is the extension that I spoke about it's it's an extension for vs code and what's really nice is that it on installs V automatically even it even does compilation automatically it downloads all the versions of s seed that are needed in the codebase and finally it compiles the the project after every change to the codebase and

it run detectors for for that codebase so the detections are really showed in real time this is the table to sum up the presentation so there are quite many tools out there some are some of them are like more specific to a given area let's say for example slitter is mainly focused on static analysis While others are mainly testing Frameworks but for example hardhead integrates also a language server as well as wake and for example Foundry has a fuzzer like a fuzzing engine as well as wake but what's probably the biggest advantage of vake is that it leads developer through

the the whole development process starting from like simple typing code while show while showing already some possible detections or problems inside the codebase then by doing single testing like unit testing or maybe fuzzing and after there are no bugs inside the codebase it's also possible to deploy contract using deployment scripts there are some additional resources we want onboard new developers to using the tool for example the official documentation I will have a QR code here so I'm just going to skip those links yeah there's also there are also solutions for eout like the capture flag challenge so we can try to check them out they are very nice and they

show some basic usage of the of the the framework and we also from time to time publish some audits like test from Audits and this is the example of Li of ston Sol iport and we also have some test for Accel and so on and finally regarding static analysis there's nothing easier than than just check out those built-in detectors and printers and that's the end of the presentation so thank you for your attention and be sure to check out the landing page of vake thank you so much a thank you and thank you to the Fine gentleman from AI as well supporting from the front row that is great um for for helping to build this

community by being the great sponsors and content creators on this uh on this conference um and we have a space for two quick questions anyone yes was that a thumbs up or do you want to ask something all right fair enough okay anyone question yes please thank you uh hey thanks for the presentation that looks really cool I'm um kers do you also have your uh like how are you doing compilation are you using Foundry or hardhead or are using your own compilation pipeline to compile smart contracts yeah we have our own

compilation Pipeline and we are doing incremental compilation so we split the code base to like very small compilation units and because of that we can do incremental compilation so this is something we are using in on the command line as well as in the language server but sometimes in a bit different way cool thank you thank you very much any other questions well I I have one um so we we we mentioned at the start it's a it's a bit of a Swiss army knife um of of blockchain development um my favorite way of using the Swiss army knife is the bottle opener for example in your particular case you're Keen to onboard new new developers what feature uh do you think that will or the use case of

using wake will be the kind of easiest kind of entry point uh into the ecosystem yeah thank you for the question I believe the easiest like enter point for new developers is testing because usually developers have some smart contracts already or they are deploying new ones and it's very easy to write a simple test case or like unit test the test the contract while developing new detectors if it's very complex but at the same time if the developers want to use built-in detectors they can just show uh see the detections right in vs code so this is something that's done automatically and developers don't even need to do something very special just download download the extension for BS code and that's all fantastic ladies and gentlemen what else do you need you've

got an Ikea manual basically here to join the Wake Community um thank you so much M of Aki um give him another hand of Applause please and we will see you very shortly yet with another talk on this fantastic main stage see you soon