DeFi Security 101 2024: Full Day, 7 November
DeFi Security Summit 2024 · 7 Nov 2024 · 7:26:59
Full-day recording of DeFi Security 101 on 7 November 2024 in Bangkok, the hands-on day before the main summit. The workshops cover finding bugs with tips from four security researchers, Foundry-based formal verification, an introduction to the Lean theorem prover, secure development of smart contract systems and Damn Vulnerable DeFi v4.
Speakers
Topics
From DeFi Security Summit 2024, hosted by DeFi Security Summit.
Transcript
e e e
e e e
e e e
e e e
e e e
e e e
e e e e
we've all had enough caffeine woken up so thank you for joining us thanks to mully and the rest of the team the organizing team the volunteers for kicking off yet another fantastic DSS starting with uh DSS 101 so hopefully we all here to learn and get better and uh who's here not into finding bugs okay maybe a couple but all of us are into finding and fixing bugs so this is this is a topic that uh you're going to be hearing from the four of us here today and um no guesses for why these this is 42 tips but we are four security
researchers so why why do we want to do this right obviously because vitalic says so just kidding but this is a tweet I mean this is sort of Representative we hear a lot about scaling in ethereum right we hear the hundreds and thousands of l2s but for all of us the security researchers here we know that hacks scams Ru pulls happen on a daily basis um and that's why we are here to find the bugs fix the bugs make the space safer more reputable and um you know and generally good for the whole ecosystem so yeah as
this tweet says I mean this I I I don't know ifalik was referring to the DAP player the applications but presumably ethereum layer ones and Layer Two so the technical risk in the bugs and code is something really really high um we only see this when things go wrong so unfortunately that is an occupational risk or Hazard that comes with uh information security so all the security researchers here you never really get to uh well it's it's sort of different in in this industry because you know whenever you participate in contests or other things and you find bugs you recognized but in general before web 3 people or um corporates are generally in the Limelight only when things go wrong
so um you know that's that's something changing in web 3 so that's that's what we here to learn um and these are I mean these numbers are really the smart contract hacks and this is from defi Lama these numbers have been going up so as you can see the trend the I think the tallest Bars were really the bridge hacks uh from hopefully a couple of years ago and uh things things sort of look better from this but I don't think this paints a very um you know accurate picture so so I don't think it accounts for all the user risk the fishing and so on so this is I mean we want this to really sort of taper out right so that's that's why we
are all here today all right so who are we I am Rajiv I've been a security researcher for a long long time um had a brief stint with trail of bits um and then and that's when I got into etherium security smart contract security around 2016 uh participated in as an early par spent in many of the audit contests uh but for a couple of years I've been doing collaborative reviews uh as a lead security researcher at spearit Cantina I'm also the founder of secum which is U uh really known for its ethereum security boot camp and trustex the event so that's me but I'm here joined by my smarter colleagues and uh we'll have
them introduce themselves everyone I'm Nat I'm also an independent security researcher I've been doing security since 2020 um where I also was at chobits um before that I was doing blockchain development in the most recent years I've been doing a lot of um code review as well as invariant development horen hey uh my name is Jan and uh I've been in the space for six seven years now um been working on a lot of tools and tooling some of them you might know some of them you might not I started out kind of with um mythal symbolic execution um and I won't bother you with
all the others um I am also a somewhat active Bounty Hunter I really enjoy it um and yeah cool and I am hiup or Desman is my real name I'm also a independent security researcher joined the space in 2017 so it's uh really nice to be able to uh translate to web security and uh help to Kure the space cool and with that we can start with our first 10 tips so um the agenda is we have 42 tips we're going to sort of split it up amongst the four of us and at the very end there is actually a workshop quiz
which should be very interesting and it does have some rewards as well so please stick around and uh yeah have fun thanks cool awesome so let's get started with our first tip it's about challenging your intuition and assumptions and to kick things off uh I'm going to make this a little interactive so I need you guys to take out your phones and do the slido uh so let's have a little quiz to test some of our intuitions okay um so do uh join or you can just go to slido.com and ke uh the seven digits that you see there and I should start seeing your names uh pop up and the quiz section and you can be anonymous and so
on unfortunately it's uh the free plan so I only can allow up to 100 people to participate so once I see uh that number then I'll proceed on to the next slide awesome awesome the numbers going up nice I see some familiar names all right I'll give you guys maybe just another 20 seconds or so to join and then so is this uh it's just like a simple tree question kind of thing um to see how well you can challenge your intuition and understanding okay I give another five seconds so
four three come on let's hit that [Music] number okay and we're good okay so first question uh it's a statement true or false right I recruit my losses right the meme coin I bought pump 50% after it's down 50% is this a true or false uh you have about 20 seconds to answer okay yeah oh wow good job uh for those of you who answered false that is correct right so if you work out the math if let's say your coin that you bought is at a dollar it goes down by
50% % it's at 50 cents and goes up again by 50% it's at 75 cents it doesn't break even so that's a simple warm-up question and uh there's also like a timing right so if you can answer as fast as possible then you'll be on top of the leaderboard and just for fun okay second question right so I am 31 years old I'm introverted relatively bright and I majored in app meth I'm deeply concerned with issues like front running and me right so which of the following is more probable I am a security researcher or I am a security researcher specializing in [Music] me which one would that be huh wow okay it's not too bad not too
bad uh for those of you who chose the first option that is correct and why is that so because using basic probability Theory you'll know that the first category the second category is a subset of the first so just by the fact alone the first is more probable right hey rajie is first and somebody is imitating me in second place cool all right last question so a frog is stuck at the bottom of a well that's 5 m deep each day you know it jumps up by 2 m but slides down by meter so on what day is it able to jump out of the well mean it's like two and then you know minus one and then you know just
got to work it out and and might feel intuitive that know maybe you might gravitate to an answer more than another but we'll see okay not okay not too bad not too bad and those of you who chose the fourth is correct so if you work it out logically it's an AG case right where on the fourth day you're at 3 m the the frog is at 3 m so it jumps 2 m it exits the well it doesn't does have to do that slight uh down biometer so it might seem that the the fif day is a bit more intuitive but no that's actually wrong and so this kind of like gives you an idea of
challenging what seems to be correct it feels correct but it may not necessarily be so right and congratulations to Desman 2 awesome wow good job okay so we're going to look at couple of real life examples uh that I kind of have uh experience uh through my uh Security reviews and the first case is fee equivalence right so for instance uh you can see these few lines of code um you have a swap fee and usually indexes you are able to specify I you're swapping uh the exact input or the exact output right so um this is how the swap Fe is calculated right you just uh take the
fee in uh basis points multiply by specified amount and if if it's in exact or uh input or exact output then you just uh subtract or add the S fee right and this might seem to be correct right so as an example here right if I swap 100 usdc for die at paral one to1 assuming the Fe is at 1% and I specify the exact I specify an exact input right so what does that mean it means at 1% It means I take one usdc as a fee I should receive 99 die back right so the fee equivalent in a sense would be that if I specify 99 die as the exact output I should be the Dex should be requesting 100 usdc in return right and the problem
is if you work through the math here uh it doesn't really add up right um 1% of the 999 is only 0.99 so if you add that you're missing uh by 1 cent so you don't really have that exact uh equivalence so what's the fix yeah it's kind of you kind of have to change the denominator a little bit and that's the correct math so again it might seem those few lines of quote that you've seen previously might seem correct but you kind of have to work up the math and let's take a look at another examp oh yeah so if you work this out then it would be correct um let's take a look at another example right which is taking fees in chess uh this is uh Twitter tread by sing 0 so
just a credit to him um but you taking uh fee in shares is quite common right especially if you have autoc compounding vaults like ERC 4626 right so protocols tend to want to take fees in shares because it's autoc compounding so the amount of fees that they get will uh increasingly ACR in value over time right so uh this is the formula that they use right so it's the harest amount multiply by the fee and then uh multiply by the total Supply divided by uh the underlying value uh so let's take an example right so say you have a 20% fee and you harvest 100 e right so technically the protocol should
receive 20 e in fees and uh let's work that out right so the Harvest is 100 e assuming we have a total asset initially of a, if uh so th 100 if multiplied by the fee which is 20% uh the fees specified in basis points so then uh multiply by 100 shares and you divide by a thousand so yeah just uh replacing the numbers with the variables uh you'll see that uh the number of shares that are minted is 1.81 right so the question is is this 1.81 shares equivalent to 20 e right and you realize that it isn't right and so
what's the reason behind it why is it that it's less than the 20 e that's expected well if you think about it you are actually diluting the share that value because you're meting extra shares so you have to account for that share dilution right and so this is kind of the correct formula that you are supposed to use instead and uh if you work out the math then you like you end up meeting slightly a bit more shares which will uh give the protocol a little the uh desired 20% right so again something that looks really intuitive it looks really correct but then if you once you work out the math it doesn't work out right so that uh is my first tip of on challenging assumptions and uh challenging your intuition okay so tip
number two scrutinize the start and end of life cycles right um usually the start and end of life cycles are a bit more uh age cases right so for instance let's look at initialization right is the condition for in initialization explicitly defined and if it's implicit can it be exploited uh and we've seen those happen in Real Life Cases right uh the first is in Balan of V2 where uh I highlighted in red you can see that they there was an initial condition where uh you could uh exploit the case where the circul the circulating Supply is zero right and you cause the pool to be reinitialized uh by resetting the rate to one and the other is the meme attack
that happened earlier this year right where uh the uh the tldr is that you're exploiting the initial condition of the one to1 uh shares to Value uh mean the borrow share to asset ratio right so if you can get the system to a state where uh you have more shares equivalent to one way of value uh then you can exploit that initial condition so uh you do have to kind of take a look at the start of the uh life cycle and also consider the end of the life cycle right so is there any state that is supposed to be totally reset but isn't and uh conversely is there any that are not reset but they should be right so for instance um
lingering approvals on token or ownership transfers okay um so this is a finding by watch Park uh for a contest shock contest where they found that expired locks uh you know like once you have a you if you know the V uh token model of locking out your tokens to uh receive more rewards then uh once the lock expires you know what is the state of that uh uh condition right um and in this case you know expired locks are considered the same as deposit with no locks right so there should be a way to kick out uh expired locks okay so tip number four right be familiar with multiple Frameworks right
um Foundry is mostly widely used but there are projects that still use H head right so there might you might be spending time pting uh the setup the logic over to Foundry uh and that is kind of like a trade-off and so it will be good to still be familiar with multiple Frameworks like hardhead but it could be worth it if you are using uh exclusive features that are features that are only exclusive to that framework so for instance like invariant testing or fast testing might be more popular on Foundry so then it might make sense to kind of pot over uh the test Suite from hardhead to Foundry okay tip number five run coverage if possible um
unfortunately more often than not I run into this shoe of Stack Tod when I run uh with Foundry with uh even with the IR flag on um but if you can run it h it's a really good thing especially if you pair it with coverage gutters which is a uh useful extension right so if you run Forge coverage uh with uh you run this line right uh and then you turn on the extension you can display the coverage so you can see uh you will have three different colors right so green means the the coverage uh that line is covered if you see yellow it means either it's you're not fulfilling the entire coverage you are missing out on the branch coverage so it's either the if or the else branch that is not covered and
if you see totally red then it's not covered at all right and if it's red then those are prime areas uh to uh you want to scrutinize those uh areas further because that's where bucks might tend to lie more uh some other useful extensions like spell checker uh the solidity uh extension bomic Foundation uh so here one one example is that if you kind of like highlight over the function name it kind of gives you the uh parameters and uh the variable types and the other useful extension is the solidity inspector where it shows you for instance the contract size and it shows you redundant import right so you
can see here it's an unus import the console uh import there okay tip number seven you want to mock minimally right so as much as possible you want to use actual implementations and network conditions right and the reason for this is that different networks have different Behavior so for instance uh Trent op codes might still not be supported on some networks uh or for instance like solidity globals might return different values um for different networks right so I would highly recommend doing uh F tests uh especially especially if the project that you are auditing is integrating with other projects so instance like using uh aat using the DSR uh MERS DSR yeah okay tip
number eight mess with the code um so you want to try reimplement try reimplementing uh certain function to differentiate against right and you might be able to spot s some subtle differences and you might then you will start question like why is it that I write things differently and it might help you to uncover subtle B and ideally you when you do the change right uh it should C cost at least a test to fill and that's kind of uh the idea of mutation testing where you are kind of testing the strength of the test Suite uh yeah so if you notice I went from tip number two to tip number four and that is where tip number three is and it's the idea of thinking what is absent right so it's very easy to spot
what's actually present what's you're actually seeing on screen uh it's yeah it's very easy to identify issues that are written rather than Unwritten right especially when you are reviewing uh fixes and I feel that's where things tend to be a bit more uh tricky right so for instance this was a uh PR that I reviewed for unisoft V4 where they changed uh the V4 core and you know it looks good lgtm right uh turns out it's not really lgtm because there was something to be fixed in periphery uh that is dependent on this behavior and that was a bug that I think some of you guys here in the room f as well uh so you know you live and learn right um yeah
tip number nine uh you want to periodically step away from the code base right and the thing is that you might suffer from review for where you're staring at a code like over and over again then you start to have tunnel vision you suffer from cognitive biases and that's when you might also start to realize that you see uh patterns that you're familiar with and then that's when you start assuming things are correct but you know it might not necessarily be so so consider like switching tasks you might want to take a break or you will start uh writing some tests or write up the issues that you found already so just switching things up a little mixing and matching a little bit I think helps to keep your mind a little off and then when you come back
you it's in a way a fresher State of Mind in it sense so that would help you uh to be a little bit more focused and it might help to open that uh part of your brain that spot something that you didn't see before and for my last St it's about taking care of yourself right so you want to have for instance regular exercise uh for me I have a garment watch that I bought a few months ago to check my health uh to check my sleep as well so it's uh really important to take care of yourself physically mentally right um touch grass take a vacation right and I I feel like this is like really important because uh if you want to be like athletes you want to be uh at
pick performance it means you need to be at Peck condition so uh those are my 10 tips and now hand it over to horen thank you here you go okay so um my background is as I said before uh in uh automated tooling automated security analysis but also in Buck bounty hunting and today I'm going to kind of focus my tips on that second part the bounty hunting and not so much on tooling and using using tooling um I think a few tips later on we'll uh cover those and my first tip is kind of has a
little bit of overlap with the with the previous one take care of yourself um pacing um on Twitter sometimes uh you kind of get a sense that um audit contest book bounty hunting they're all about the grind set and grinders um and I honly believe that is like the worst possible approach uh to doing any kind of really good deep security research and I think like a couple of examples really outside of security research will show you that this kind of makes sense so there's a um if you look at doctors they also or tend to have a
culture around grinding like taking multiple shifts working really long hours and um not sleeping that kind of stuff and the data shows that uh more people die because of this like there's more more uh risks that are introduced by like this type of grinding behavior and I feel like or I think the the same is true for auditing or security research this is like a very tough mental task that your brain is not able to do for like long stretches of time like you need to give your your brain time to recover and digest um and to to
give an example like I used to be uh have a course in University it was a while ago um and we had these um challenges in this course where we got a day to solve some networking challenge uh like you build some kind of protocol like it was very interesting but for me what those days looked like is me just going like tunnel vision for 4 hours until lunch and then um i' take a walk to to like to get my lunch and during that walk I solved the whole issue like I would be stuck for four hours basically then 15 minutes walking I
solved it so it's really important to to give yourself or your brain like this this this time to rest and digest to process uh so you actually yeah yeah work more optimally so I think taking it easy is actually a more productive approach in the end this is not to say that discipline isn't important and also not to say that it's not a lot of work to like build the skill build the knowledge necessary to do bounty hunting or security research but just that when you're doing it eight hours straight or doing more than eight hours of reviewing code I'm not sure that it will work
well okay tip two I think there's a lot of value in uh scoping out targets for bounty hunting um if you're like me uh you have limited amount of time available to do bounty hunting on a single Target at a at a certain certain point in time so for for example I'll have a week or a couple days um then it doesn't make sense really to go for like a an L2 implementation like it is just too large so I think it makes sense to to then uh pick targets that have about the size
that you can handle or that you think you can find something interesting with the amount of time you have other things you can look for in uh finding bug or Bounty programs to hunt on or I guess other contests is the the type of program uh if you're very familiar with l2s uh with Bridges then finding bugs and bridges and l2s is going to be easier uh if you're not familiar with those then it's going to take a lot more time uh and you're going to be more efficient working on things that you're familiar with that sand it's often like a good idea to switch things up to make sure you like stay sharp and uh and
everything then there's one more thing that's not really about you but about the program itself and this is something I kind of look for in Bounty programs it's the the medium and high payouts because often a program will be like ah here's a couple million for critical bug and then they won't pay out for highs uh and this kind of tells me uh something about the mindset that people have running their Bounty program um being not so much interested in improving their security reducing risk of hacks but more so kind of like catching just the worst case scenarios um and uh I have a feeling that like even if you
find something you'll have a hard time getting a like a good payout out of those those protocols so I I tend to look for that as well okay tip three uh this kind of overlaps with my first tip a little bit um and uh this actually kind of happened to me so I was trying to sleep uh lying in my bed and then uh i' spent the day like looking at some code and my brain is like yo what happens if you liquidate your own position and I was like oh um so in the middle of the night I was tying up a bug report cuz well I couldn't sleep and the tip here isn't really to try to sleep and then do bug bounty hunting at
the same time that's probably not a really good tip um but it's really about uh a mental model of the top idea on your mind um this a blog post I I forgot uh where it was posted but the idea is that you basically have like a a place in your brain for a thing to work on when you're doing different things so let's say I'm doing like doing bounty hunting on a specific project and then I'm going to take a walk or I'm GNA do the dishes clean like the house that kind of stuff during that time your brain is kind of like passively
processing things and so for me like a not insignificant amount of bugs came from this in like passive processing time so to really optimize on this make sure that you're not trying to do too many things like if you bounty hunt and then do two hours of I don't know trying to learn something else then your brain is wholly occupied with this other thing and not working on the bug Bounty thing anymore so if you just like make sure that you work on bounty hunting and then give your like brain the passive processing time that might work out really well for you okay then a tip on Buck Bounty discussions um Buck bounties are great uh but unfortunately if you
submit a few you'll probably get in a situation where the protocol team does not agree with you it happens uh every discussion is different every team responds differently it's usually a high stake situation and you're telling someone hey your code doesn't work um often unintentionally there's going to be fallacies uh it makes sense to prepare for those fallacies in a way that you can handle them in a like a in a good way uh not just saying hey that's a fallacy you don't know but just handling it in such a way that you can move the conversation onwards so there's couple lists on the internet you can
look at them be like read for them see how you should respond it's a really good way to to improve your speed I guess or improve your productiveness in these discussions another one uh thing you can do to improve these discussions is kind of change your mindset I saw like over time I've seen tweets that kind of indicate like this adversarial mindset of like um this project sucks and they're not giving me anything um that usually doesn't work out really well and I personally like to take a uh perspective of like I want to work with this project in the future I want to
submit more books I I might want to work with them in a different different capacity so I adapt my self communication to this and that ends up being a lot more productive or I think it ends up being a lot more productive then the more adversarial hey you need to pay me because XYZ okay tip 16 diversify your skills this is a somewhat cheesy one but really anything you can learn outside of just web 3 security um it's going to be useful so there's a couple lists here like learning how compilers work can be super insanely useful because then you know how solidity works you can know
about the quirks like the issues that people might encounter everything becomes a lot more logical and also like compilers in general make like your understanding of programming languag is like insane um another thing I really like is like don't stick to web 3 related topics necessarily um there's a book called How to solve it um I'm not sure how to pronounce the author's name it's a book about how to approach mathematics problems um in a like there like a strategy about like solving the the issues and creating proofs um and I really like that because it's kind of teaches you a different way
to think about things and the more ways you learn to think about things like by learning about different topics the more ways you can use to find actual bugs uh so yeah I think this is a very useful thing to do okay some specific bug hunting strategies I think um something that works really well uh is to find a specific Paradigm and specialize in it um so for example uh in defi you have a lot of systems that allow you to have uh these Pro systems have problems uh liquidation is usually very difficult to
do right um and there's been tons of bugs there um so what you can do is kind of learn a lot about how these different systems work what their pitfalls are and then once you're really comfortable with them you can probably just go on immuni list all the different like types of systems that might have leverage go through all of them and see if the pitfalls that you've identified or learned about um are apparent in these these uh implementations and then well you report them obviously if they are there so in defy like leverages one example I think uh it makes sense to have a look at like what's like current
uh like a a paradigm that is currently being developed like um like concentrated liquidi in ex example where there's like Unis swap released um their version and then like a couple other projects will also have like all implemented their concentrated liquidity and um if you were an expert like you might have known that tick Transitions and uh ending up like right on top of a tick and can be a really difficult thing to implement uh which is led to some hacks unfortunately um and like in that way you might have gone through all the implementations and found issues related to that type of like difficulty in
implementing this kind of Paradigm uh I think like ZK is an example where there's not that many people that I know at least that are specialized in U these kinds of systems U so there might be a lot of opportunity there I don't not sure but I think the general approach of finding Paradigm specializing and then going broad can be very effective because you can go really quickly through a lot of pro uh B Bounty programs okay that is kind of the go bro approach um there is also a go deep approach and this is kind of the one I
tend to follow it works really well if you have like a very limited amount of time um um which might be like a week or a weekend um and it's kind of like this explore explore exploit type problem so what I do is I kind of like explore a code base or usually I just start reading documentation actually um and then I identify like points of interest or things that I think are going to be difficult so it's really like it it's has some overlap with the the Paradigm specialized strategy um in the sense that you like identify the
potential pain points and then like go for those once I have like the list of things that I think can go wrong very easily then I just go deep into the code see if they do these things well and well sometimes they do sometimes they don't uh and when they don't like you can write up your buck report uh what's really nice about this approach is that um it kind of leverages the fact that as a buck Bounty Hunter you do not need to write a an audit report that has to be complete like as an auditor you want to make sure like you find all the bugs not necessarily all the bugs but you need to find uh give a comprehensive report that
will allow the project team to build like a really good and secure code base as a bounty hunter you just want to find one bug uh that's your goal or like one critical bug I guess and because we have this we don't have the limitation of having to find comprehensive bugs we can um focus on just those parts of the code base where we think there will be bugs and over time you'll get a kind of spidey sense of what these parts of the code base are going to be like um and you're going to be uh like browsing it through a code
base and be like hm this looks fishy let let's have a look at this um I think this works really well uh so I already mentioned reading documentation is kind of the first part of this go deep approach I think reading documentation is sort of an underrated not that much talked about approach um there is a lot of bugs design bugs that happen that you can find by just reading the documentation some ideas just fundamentally don't work or fundamentally have some flaws that people need to uh worry about um so you can find these mistakes or critical
points but just reading the documentation uh and then seeing if they actually implemented the necessary safeguards so this is actually a like a relatively fast way of of uh approaching a a project um yeah and then finally um there's a toolbox mental model uh and I really like this one so a lot of critical bugs aren't critical bugs necessarily so if you have a report on immuni for example a boundary report what's very important is the impact of your report and to get a critical impact to
drain all the funds it's very often the case is that it's not a single bug that leads you there it's often like a series of bugs that will allow you to get around various safeguards and measures um to actually end up in a situation where you can take out all the funds so we commonly call this a killchain and what I tend to do when I review a code base is I mentally or actually write them down sometimes keep track of these tricks and gadgets that I found um in a code Bas and the name gadgets is kind of Solem from binary exploitation but the idea is that if you find um like
a I would almost say it's a a low severity vulnerability if you find a way to make the system do something oddd or weird like maybe you're able to get a system to uh go like right up to to a certain margin requirement uh that is not expected but also not a CR like a vulnerability um that might be a useful thing to set up a killchain so when you're reading through a code base and you find ways to do like weird stuff that's not necessarily A vulnerability just write them down or keep track of them so that when you find an actual bug you can have a look at all these gadgets
tricks that you found and see if you can change together to end up in a situation where you can actually exploit the vulnerability uh and get um some some decent impact all right um those were my tips n yeah there you all right hey everyone I'm Nat so just to give a little bit more or context as to my background I mainly did a lot of code review and invariant
development and so a lot of these guides are going to be kind of somewhat code review related somewhat invariant related and some tooling related so to start off with I think the first thing that at least I encounter when I look at code bases is to FOC is like kind of reading through code and then realizing that certain pieces of code are much more complicated than others and those I think better better than ever usually there's a bug or some unexpected behavior in those cod in those parts of the code so these I kind of separated the tips into a few different sections um I'll start with kind of tips on uh reviewing kind of complicated code how
to break it down into something that you can better understand and then to kind of form that into um something you can better kind of English englishes size with um expected behavior and then a brief talk about tooling without getting into specifics so I think one underrated tip that I have is to take complicated code and then write pseudo code based on what you're seeing so as an example okay sorry um as an example um if you have for example a calculate and distribute rewards function um you can e fairly easily break it down into for example part one um it
calculates um some amount of like how much should be distributed to certain users um and then you can then split it up into the actual distribution so the actual transfer functionality um and then obviously after that it has to change certain values the benefit of this kind of practice is it takes you out of the code base and takes you into more more of a high Lev review of what a certain function is doing um because a lot of the time the function name is not actually going to match what the function does um or it's going to match maybe a little subset or a very specific behavior of how developers expect users to interact with their system but not um the entire scope of how a user would
actually interact with that function so at least for me when I pseudo code things out I'm not focusing on whether like for example the user rewards is the correct amount or like whether there's a rounding issue um it's more of a highle understanding of like what does this function do and once you understand that then you can go deeper down into actually like analyzing arithmetic or um in this particular case would be arithmetic but could be really whatever um that function focuses on my next tip is to play around with the unit tests unless you have none um a lot of times um the first thing I will do at least when I um clone a repo is to
run the unit test and see what the output looks like ideally as hiccup said run the coverage but sometimes that's not actually possible but it does tell you a story about what the developer was thinking when they were building this function if you go back to like even just the calculating distribute rewards if there's a unit test based on that function then you know at the very least hopefully um how the how the developer intended to use the system and how the how essentially the developer um you know forms arguments forms like the function calls and like what the expected behavior is it can give you an idea um it might not tell you exactly what it does but it will help guide your
understanding of what is expected you can play around with these unit tests in ways that um I think is that allow you to manipulate the code and play around with like say changing an argument or invoking a um functional revert for example if you're looking at the client code you're looking at the unit test and there's no test for like the rting case I think it's actually at at least insightful to kind of manipulate that unit test to invoke certain functions or certain paths so that you understand like if you have for example nested if statements that you understand how what is required to actually hit those statements um
the benefit of that is a lot of the time developers are also going to go in with the assumption that you know users are only going to use this function in this specific way therefore this if statement is only executed under these conditions um and with the unit test you can very easily um be able to test that Li in livetime and when you actually get to code review or like um in the future if you do get to invariant development stuff it also means you have a better understanding of how that function works and how to get a proof of concept up if you need to I'll emphasize while you're doing this and maybe this ties into one of my later tips as well um is to document
everything you notice about the system so I think um whenever you look at a code base it's going to be really clear that the developer made some kind of assumption while writing this function um on how it's called or how it's executed um and making sure that you write down everything you notice about the function is useful later down the line for um in variance as well as as reviewing the system my next tip is realizing that how developers want users to use their system is not equivalent to how users are actually going to use it there's been a lot of
times where developers have assumed the users always is going to use their front end or a certain backend to interact with a smart contract um or that users are always going to use this very specific periphery um to interact with one that's a dangerous assumption just because the nature of smart contracts unless you have that access control check on your smart contract to make sure that you know only certain users or certain users have to interact with your contracts in a certain way um if there's any kind of differential between those two expectations that's a bug in the system um and usually a fairly High severity one all right so these tips I think um
help under help you understand what code is expected to do but that doesn't necessarily go into actually finding invariance so um my next few tips will be based on finding invariants to take a step back an invariant is basically something that you expect your in your system to hold true so that could be something that's based on like a function if you call a function you expect something um some Behavior to happen afterwards or it can be based on the entire system as a whole usually the system and variance are going to rely on system behavior um System state generally with um data structures but this particular tip is based on functions themselves so if
you're looking at a function um you can essentially use kind of the practice with like playing around with unit tests you can eventually determine what are the conditions required in order for a function to succeed what are the conditions required for a function to fail and if you just start even just creating a list of all of those cases you have at least um created started to create a list of invariants that you can later check on the code base this is important because again it's really easy to look at code and get stuck in the details get stuck in like certain flows um but this practice will help you kind of step away from the the depths of the
code and be able to compare like behaviors of different functions this next tip is around expected behavior of the system in terms of um more of a high higher level this is related to like State change is um what is expected to change within like different functions so for example I think the most colloquial example is the deposit withdrawal should be um kind of opposite functions whatever the deposit does and whatever the state variables a deposit function changes the withdrawal should essentially reverse those you're looking for any kind of behavior that you can kind of be able to link in terms
of patterns um if one does one thing the other one should be doing something else these invariants also um or this practice at least also helps you get out of um kind of very specific like nitty-gritty in the code all right so yeah you have a list of invariant I think the invariants help but you you they're not actually useful unless you do something with them now the first thing I hear is but I don't actually know how to use a certain tool I don't know how to use Foundry I don't know how to use um meduso or whatever the tool cool is and I'll preface this with you don't need to for this talk because I'm trying to keep it as high level as possible um so that you can use
these invariants during your code review during your um whatever whatever practice you're doing um and be able to use these invariants in a way that will help and guide the process of your code review so generally when I go through the practice of actually finding the invariant what'll happen is I just have a list of say like 50 55 invariants that I'm not 100% sure on all and any of them um but very likely every time I look at the code base and every time I look at the code I understand a little bit more and therefore can refine the invariance to
be even more specific or to highlight assumptions that maybe weren't um visible before I'll emphasize document everything you're not sure about because in the future um depending on how long your code review is of course but in the future if you're kind of at a loss and you've looked at the code base for a lot of for a long time you're not entirely sure what to do anymore these invariants can help as guidelines for future things to explore just because it's something that you've may be identified as unexpected behavior and then therefore you can um continue to trace down those paths um at the
end and I'll preface this with you don't necessarily need to you need don't necessarily need a fuzzer or like a unit test to verify these invariants I think it's more important that you review the code base with these invariants in mind because then you can um for example if you're looking at relationships or assumptions between functions um you're you have a better idea of what to look for what does unexpected Behavior look like um and where the potential bugs are so with that um essentially never trust users users input always have the smart contract verify them um that's where a lot of the invariants are based in um and are
related this is kind of echoing some of the previous um tips on tooling and I will emphasize that yeah tooling is really hard to use sometimes I think it takes a lot of time to understand what would you use your tool for what um but I think the more time you spend using the tools the more you understand um the quicker it is every time you use these tools to spin up like a test um for example if your background is in if you if you know how to use like unit tests um in a way that's very quick for you and I think there's there's bit always been kind of a discussion between um fuzzer versus fuzzer like tester or
framework versus framework and I don't think that's a productive discussion I think it's more about playing around with the different tools play around with what works for you and identifying how you want to use the tools so related to tooling each tool I think was created with a slightly different purpose some tool might have been created to get um invariant testing up fairly easily some tools maybe require maybe were created um in order to test very and find very complex issues and at the end of the day every tool has its limits but every tool has its pros and cons and taking the
time to actually understand what do you know about each tool um and how you can use these tools during your code review is important for example if you take one of those previous invariants that you found and then you write like a unit test on it yeah sure that might not be fully um that might not prove like a lack of a bug as much as a fuzzer or like a verifier approver might um but at least you you're you're using the tools to to your advantage more than you would as a manual reviewer you're at at the very least increasing the scope of what you're learning um and what you're providing to users and and Developers for your code
base and once you actually get to finding bugs um finding unit test failures finding fuzzing failures I will emphasize that um any failure that you get from any tool that you're using is a potential bug in treated as one because the bug technically speaking could be in the client code could be in your unit test could be in your fuzzing code could be in your mock code could be at any stack and if you're just changing your code just to make a test pass you don't actually know where the bug was um and therefore you your test might actually be masking a bug in that I think um there's there's kind of an endless discussion to be had
on kind of the rabbit hole of of reversing like why a certain test failed um and I think taking the time to really understand um every layer of the code so the unit test the whatever test that you're you're writing um and the client code is important because um from there you you could there have been a lot of cases in which um fuzzer found a bug unit test said it wasn't a bug it didn't actually it didn't actually fail but the fuzzer did and um it was because the unit test and the client code was incorrect correct and so realize that there could be also multiple bugs in all of the different Tex Stacks um and
realize that your unit your your fuzzing test or unit test could Al could also be buggy um I think that's probably the the biggest lesson I've learned um while writing these invariants is realizing that um or in other potential cases you wrote the invariant you wrote it like week one and then week three you're coming back to edit one of your invariants and you're realizing that's completely incorrect that's I think a very common issue with any kind of testing um but especially for code bases that change so quickly I think the more time that and the more stringent we are with testing and testing practices um I think the the
more that these these code these um tools can help us find these bugs and essentially make us more well-rounded security researchers so that's all the tips from me I'll pass it off to [Music] [Applause] reiv thank you Nat so hopefully um we have not reached a Tipping Point with with all these tips and finding bugs those were hopefully some really good tips From The Trenches right so as
you've heard their introductions they've been doing this for a long long time so all these have been sort of distilled these may seem very simple and obvious but we believe that's that's what it really is right so with my tips I would like to take us sort of zoom out so going From The Trenches really going to uh let's say the troposphere if you will right and sort of reexamine some of the concepts that have been discussed right as steps so the first thing that I always like to talk about is everything in security boils down to this right so for those
who have done security Theory it's uh you can think of it as an access control Matrix so it's really all about the assets without assets you know there's really nothing to do or steal or hack and obviously if you have assets we need actors to act upon the assets to deposit them to withdraw them to do anything else with them and all these are actions right so the first thing in security is really about assessing assets what are the assets who are the actors and what are the actions manipulating those so in this meme you see that
um Billy right Billy's parent I don't know who that person is but they want Billy to learn about money and the importance of smart contract security but of course Billy is too anxious runs off to what looks like a vending machine that really has all the assets right so the actors here are Billy presumably the the person handing the bill itself and um there are various actions here you just see them sort of depositing money and maybe getting the assets but this is this sort of sums up in my head what we are trying to do with smart contract security right so you have assets all the things we talked
about so the first thing that we should really aim to do I mean here we're talking about smart contract security but in general in security is what are the assets where are the assets in our case it could be a simple eth it could be various tokens any representations of those and then the next question is okay who are the actors and actors in in the case of the blockchain systems right I mean remember we are dealing with a Byzantine failure model right so it's not just the users who are the actors it's the developers themselves right we've all heard of Ru
pulls scams so those they are actors as well you have uh governance for example all the token holders who may decide to upgrade contracts and change a whole bunch of things within your system they are actors as well right so there are various categories of these assets that we need to sort of understand when we look at a system and of course finally the actions what is happening when is it happening right the SE matters how is it happening what are the various conditions under which it's happening and ultimately why is it happening right so just because an action is allowed doesn't mean it should
be allowed so all these are sort of sort of fundamental questions they seem very simple but ultimately this is what it boils down to so we first assess all these things and then of course look at what the behavior is so some of some of my colleagues talked about sort of expecting the unexpected and this is the reality yeah I don't think you can see this laser but our expectation may be totally different from what the reality is and this is I think way you know way more real in the
web3 world than it is than it's been in uh earlier with web2 and others right so if you sort of dial back and look back at the history of information security there's really two two categories there's something known as historically as misus detection and there's something known as anomaly detection so misuse detection for all the antiv virus you know 20 30 years of research you know what what the signatures are of all the bad things which is good but then you can never really keep up because attackers keep innovating and anomaly detection is where you really build a model of what is allowed by your system and then you detect what the anomalies are right and
anomaly is anything that falls outside this model of what we think should happen so categorizing this sort of the normally and the anomaly is important at a high level when you look at a system specifically a smart contract system a protocol now notice that all anomalies need not be bugs right it may just be our failure of capturing what a normal model is and this this capture capturing maybe in the spec in the invariance in the documentation in just our understanding of what the system is but it's really a small subset of these
anomalies that that end up as bugs and we call this bugs because it's sort of convenient I mean it's security purists really find it U annoying because you know the bugs are really meant to be annoying they're never really meant to sort of cause uh real harm so even these bugs which are a subset of anomalies may not really be vulnerabilities right and this like youran mentioned in bug bounties some of these may be you know denial of service and uh temporarily so it may not even be a permanent thing it may be a loss of funds but those May really be fees under five different conditions so those may be minor annoyances right but here we
really talking about I mean we we we want to cover the whole Spectrum but if you want to prioritize you want to sort of prioritize the criticals right we want to prioritize the real vulnerabilities and vulnerabilities are what really result in loss lock of funds and so on we'll talk a bit more so expecting the unexpected so as you see here the users and and Nat mentioned as well in this scenario the users are really coming in we don't know you know uh who the attackers are really I mean this is an open permissionless system so anyone from the outside we really don't have a periphery right it could be uh
somebody in the government governance we have seen governance attacks it could be you know even the developers we have seen Ruck pulls and it could be you know coming outside the system as well it could be any of the dependencies the tool chain that may be corrupted and there are numerous examples of these on a daily basis right so that is really what we are up against and finding bugs finding vulnerabilities in each and every one of this is really what what we're up against so it's really tricky very hard problem so the first thing like Nat and others mentioned as well is assumptions assumptions are the
mother the root of all bucks right period so the assumptions could be from the Developers it could be I mean it really starts all the way in the life cycle right it could really come in from the design of the protocol there could be some fundamental things that cannot be inherently uh solved on a blockchain so it could stem from there it could be in the specification it could be in the implementation it could be in the testing it could be even amongst us when we look for bugs right we're making certain assumptions and those
assumptions may be incorrect and actually may lead us to miss out on certain bugs so question everything right this is easier said than done and it obviously depends on the context so if you're doing um let's say in this case bug bounties right you can question everything but you may not actually get the answers from the protocol or from the platform itself in the case of audit contest it used to be the case that you know uh the developers are on the same Discord or whatever Channel or whatever
platform you're on so you could ping them but then we hit a scaling problem when you know some of us started out there were like 10 of us uh looking you know actually competing in a contest so it was U not a problem back then but today it's a good problem to have we have thousands of security researchers including many of you in this room who are on these contest platforms so if you question everything and we want sort of authoritative answers from the developers it is not scaling right so do question everything try to resolve them to the best of your ability and see where it goes qu I mean where do you start off
again basic questions right right who the actors what are they trying to do why are they trying to do this can can a certain sequence be allowed can a certain set of conditions uh happen when are these conditions valid when are they invalid right and where it could be a certain set of tokens it could be a certain set of conditions it could be a certain set of actors or functions all these things are fair game to question so that is is really the mentality to go with when you start looking at a system to find bugs and the goal obviously is to
discover misuse scenarios right so use is sort of well understood relatively speaking you look at a protocol you look at a code base you know you see certain flows you see the deposits and the withdrawals and everything in between so you understand the uses as security researchers our goal is one to understand how things can be used and really the end goal is to understand how these can be misused right and again here misuse may be okay it may be outside the realm of what is considered acceptable usage but not
everything that can be Miss used is really abused and by abuse here we mean things that lead to a tangible loss lock anything like that so these these become critical again depending on where you are so if you're looking at bug bounties a misuse situation may not be really um you know very interesting for the protocol but if it can be abused in certain ways in certain conditions maybe you know ideally you don't require any other condition for this to be abused then that is something that's really really bad right so really what we are trying
to do here is we are trying to map out the attack surface right that's really what it is I mean all these bugs that we trying to find are really entry points into the system for the attackers to abuse so that's really what we're trying to do great so now let's say we have done all this we have questioned everything we've uh made you know no assumptions we found bugs we found that they can be abused the next big question which is becoming a hotter topic these days is how do
you objectively and I don't think we are at a point where we can quantitatively do this yet but it's all very qualitative but how do you evaluate the severity of a bug so this is something that's been evolving in the last uh few years as well for those of you who have done this you're you should be very familiar with the uh severity Matrix right so you have impact you have high medium low then you have the likelihood high medium low high high becomes a critical you know you know what the other boxes are so severity is really impact times likelihood right now what's impact I
think of the two impact is well impact is really how it hurts or where it hurts the protocol impact I think is more objective right because you can really specify what is happening to the funds what is happening to the protocol is it uh are the funds being lost are they being locked is it a temporary thing is it a permanent thing is it happening to all the assets or is it happening to a few of the assets so all these can be relatively specified in a in a sort of
objective manner right it's it's hard to sort of um um disagree on this so that's that's critical to to sort of focus on the impact where it gets tricky is the likelihood right so for all the bug bounty hunters here for all the people participating in contest I mean this is a very touchy point right obviously as researchers you want to be uh fair and you want to sort of be as objective as possible but this is a two-sided marketplace right so from the protocol perspective or from the platform perspective they also want
to sort of pay out only for bugs that matter right so that's where I think likelihood comes in is this so some of the some of the metrics for likelihood is this always the case I mean is this impact is this impact going to happen all the time or does it happen only some of the times that that's critical is it conditional or is it unconditional so this is this is I think fairly obvious but I think where it gets trickier is when you start looking at the conditions right it's really how many
ifs or buts there are for this impact to happen and the more the number of ifs and low the lower the probability of each of those predicates the lower the the likelihood so this is uh something that we see on a daily basis um this is not as much typically not as much of an issue when you do collaborative reviews because there the well the the project has really you know already paid there is no sort of conditional pots or um bounties at stake the the payment the whole pot has been paid to the platform or to the researchers and the project typically um you know is is more
forthcoming or I should say does not matter as much to them if it is a medium or a low but even there the better the accuracy the higher the accuracy on our part the better right because think about it the project goes out let's say they want to make this it matters more for collaborative reviews and protocols where they want to make the report public right a protocol would you have more confidence in a protocol that has 10 criticals or that has zero criticals 20 highs or five highs get Stricker five highs or 50 mediums right so it's all today we there's a mental math that happens in
our heads I mean this is this is just the security researchers thinking right we don't we we believe well we think that a majority of the users don't even uh you know U look at these audit reports or really understand uh what to make of it right but we may get there soon so this I think is something that we need to think about and as a collective as a community we need to do a better job of sort of making this more objective over time all right so maybe there are some Star Wars fans here but consistencies right or the lack of I think that is where a lot of the
security issues lie inconsistent checks I mean this is something that all of us who have been doing this for a while you look at a piece of code you see that okay you may not know the documentation or or what it's supposed to do but just by looking at inconsistencies you realize that either there's something wrong right I mean this is the differential stuff that Nat was mentioning as well you see that there's something wrong or that the inconsistent the path where the check was missing was maybe an exceptional path where you don't really need that check right and this inconsistency is really the root of many or most of the security
issues if you think if you map the whole protocol as a uh finite State automaton a state transition diagram right you have States and then you have have transitions inconsistent transitions right on certain um certain conditions there is a transition that happens from State a to State B you would expect that it happens for very similar actions in any possible flow but then in some particular flow that transition is not happening and that may be um you know very simply it could be withdrawal it
could be um um fees it could be anything right there's something that's missing so those inconsistent transitions leads to inconsistent state which effectively is an issue right depending on what that state is if it is really the balance then we are really in a bad position so again like I said I mean these are very high level ones I mean this is where we should sort of be zooming out and thinking in terms of the protocol right inconsistencies it it could not be maybe they're not very apparent on uh Day Zero when you look at it but as you start looking at it over and over again that's
where you see those patterns emerging okay so this is um a popular meme in the web two space right this uh the image that you see and that's typically in the context of Open Source and dependencies where there is uh I don't think this works but you see the bug over there so that's in in the case of web 2 the dependency thing it's not that's not really a bug but that is like a small tiny piece of dependency that nobody even knows about right where we are operating on the top and if that thing
breaks the whole you know thing falls apart right so that's that's the meme so I just sort of uh adopted that from the web two space but I think in web 3 this becomes even more critical because web 3 is not something sort of different from web 2 it's sitting on top of web 2 and I think there are multiple things tincho talked about there is a workshop happening I think uh that's going to talk about this there is a panel on this uh day after that I'll be moderating so do do a um but if this is what web 2 is Right web 3 we have a much
much challenging task today right I think the maturity of the ecosystem has obviously is much better today than it was let's say 8 years ago and here I'm talking purely of smart contract right web 3 not layer one not Layer Two is just your daps all the protocols that we build and review there are bugs in every part of the system there are bugs in the protocol there are bugs in the dependencies there are bugs in the governance processes right and we've been slowly sort of making our way and fixing as many as we can the point here
is as reviewers to find bugs every line matters right every single line it couldn't the the amount of dollars that are at stake per line couldn't be higher anywhere else right so if for those of you who are coming from a web 2 background sure sensitive data loss breaches and so on right rcees all that but in web 3 the loss is tangible it's
immediate and usually it is IR irrecoverable right there's no going back in most cases so every line matters so when we review to find bugs this is something we need to keep in mind and as reviewers when you uh when we look at stuff right it may not be obvious in the first pass we may not sort of figure out okay what what is this line doing or maybe what is even this function doing it's okay to sort of uh proceed with gaps in our in in the understanding but like my colleague said make a note come back because every line is supposed to mean something and if it
does not it better not be there because it's a source of bugs if it not not a feature it's a bug right read between the lines as well like hiup mentioned what is there I mean this is this is I think probably the biggest uh blind spot that uh researchers sort of fall into because we are good at analyzing what is there but what is between the lines is not there so we don't think about it right so that is where we need to step we need to shift left think about not just the code that we see but about what is this function supposed to do what is this protocol supposed to do
what is this flow supposed to do and what is supposed to be between these two lines that is missing from a security perspective that I think is critical it's I mean our our tasks as security researchers is not easy read every line read between the lines and Hell read Beyond the Lines as well right what does that mean that's again going back as an example looking at the dependencies things may look okay right but there is a dependency on an oracle right or a certain API that may be buggy that may be faulty that may not be within the scope of uh
of this particular review right because we are sort of looking at only one part and I think hiab gave an example from UNIS V4 but it's it's very common right read Beyond the Lines and that's true for us that's true for the protocols that's true for everyone oops for any of the Matrix fans here just like the Matrix bugs are everywhere all around us even in this room just to sum up look at at what's there look is look at what's missing think as an attacker and this is
something that is tricky for us to do right especially maybe for people uh who come in with a developer mindset because there it's all about how is this going to be used as opposed to how will this be abused so that attacker mindset is critical and it goes without saying but act like a white hat right and this is this is something that um seal uh 911 there's a white U white hat Harbor and multiple things so look at that I think there're going to be talks tomorrow do attend so things are getting better for white hats to
actually uh act like a white hat right if they one so in terms of reporting the bugs in terms of claiming the bounty in terms of not being um uh not being sort of scared of potential lawsuits and there there on okay and this I think Nat talked a lot about invariance so this is again what a lot of security boils down to what are these properties right what what properties is this protocol is this code is this function supposed to hold the good thing is read the comments right read the code first obviously read
the comments if there are any read the docs read the documentation while things have gotten better in the last um eight years I would say Doc there's a still so much more that can be done in terms for again for the protocols if there are any developers here so much more that can go into the document mentation right that will make the protocol safer the lives of the reviewer safer make this ecosystem much much safer right docs can get better specifications even better right we have several formal verification projects
serur multiple other ones coming up that allow the developers and maybe even the researchers to specify what the invariants are of course you can have bugs in the specifications itself but at least it is a great place to start right so those can be the places where invariance can already be specified so that's where we can read as researchers but depending on the context right ask I think one thing that is missing that that is not as good as it uh it can be in the space is the communications between the researchers and the developers so time boxed audits time Box reviews um again depends on if
it's a bug Bounty how much Communications can happen depend on the context is it a bug Bounty is it a contest is it a collaborative review bug bounties maybe not as much as yuran said right I mean it can be oh yeah no this is a feature no we won't pay oh yes the the good news can be that hey yes confirmed right or uh looking at it looking at more I don't know what the labels are so that's bug bounties contest uh developers of the protocols are typically available and even the platform uh where the contest is hosted can have people answering questions about some of these properties this is where collaborative
reviews stand out right because there you're really collaborating not just with some of your other researchers but you're collaborating with the protocol itself the developers themselves are on the same shared Channel Discord telegram whatever where you can ask them hey is this a property is this missing is that missing right instead of not communicating and going away into the weeds writing an entire POC for two days coming back you know submitting with evidence only to say that oh sorry that's that's actually a feature right so that's wasted effort and we can't afford to waste uh a single
second in the space right so ask ask others ask the protocol ask other SAS ask yourself uh but do ask the final one is what is actually U actually become a a a separate field a subject within the software engineering community for the last 10 20 years actually it's about inferring invariance right so actually some very cool techniques where you can look at the code apply uh various techniques right it could be machine learning data mining it could be uh different ways of inferring what the invariants are and as a very simple example if there is um going back to web two so um if there are
mocs and frees Right Where You assign memory and where you delete memory if there are 10 paths where maloc is being done where you allocate memory and if there is one path if there nine nine of those paths have a free but there is one path where that free is missing that is a memory leak unless that happens to be an exceptional path you know triggering an exception right so this this is sort of an an easy invariant to know because this happens at an OS level or at a library level um in in um you know in your system programs but uplevel it right if you have apis where you have similar things Fu followed by uh followed by by uh Fubar on many parts on
all the parts except a few that is a Miss potentially a mess right if there are a few parts where you only have Foo but you don't have foar a call to foar after that so that that's a very simplistic example from a calligraph perspective but that is really what inference is about and this could apply to State applied to data as well not just uh function calls so look at clues in the code right especially when uh we do not have an opportunity or we've exhausted all the asking opportunities so this is where we can look at it and sort of infer and these are also clues that you can look at in the unit tests like Nat mentioned that is really where all the
security Clues are right all the paths that we tested all the um um good Cas happy cases the not happy cases all those are really laid out look at them don't get biased by them right okay last the 4th tip is there is no bug bug free code right bug bugs will exist as long as code exists just read the code and find the bugs right oversimplifying it but that's ultimately what it boils down to there can be 42 tips there can be 420 tips there can be hundreds of tools and
techniques But ultimately it's really about finding what works for you in terms of reading the code as an example you see a lot of this in this uh in this space right where um people who are just joining the space want the the next greatest road map the shortest path to success to their million dollar bound or whatever it is but ultimately it's a lot of preparation right I can speak for myself and maybe the four of us here we've been doing this a very long time and I'm not the smartest guy so many of
you are much smarter so you can do this faster but preparation is Key Practice is key but the biggest one is patience right Pati have patience with the code have patience with yourself see what works best for you that's it so I do have the sort of the privilege of quickly summarizing all the tips the 40 tips so 41 and 42 are really um sound bites if you will right of all the 40 tips the first thing is read the code think of assets actors
actions think of use and abuse challenge every assumption made in the program test when it comes to testing properties and invariance are key depth and breadth your AR talked about it you can go deep you can go broad figure out what really works best and there is no magic bullet here right you have to do both again depending on the context specialization and generalization see again what works best for you audits contest and Bug bounties have different sort of require different
skill sets if you will ultimately they all require you know the basic security thing but when it comes to sort of maximizing the outcome right it really requires a different mindset and especially these days with contest and audits Things Are also um getting interesting um they're getting very specialized in terms of with all the conditional parts and the different sort of combinations of all three right you have pest that look like bug bounties that are sometimes um thought of as audits or reviews scoping is critical scope out ultimately it's attack surface but the scope that is there for you for the review that's
critical and then once you know that how do you sort of pace it right do you go fast is it a Sprint is it a marathon um do you want to run slow run fast it's that's a tricky thing to look at zooming in and out I mean this is this is sort of one of my favorites we sort of get into this tunnel vision like U hicup mentioned where you zoom in and you're focusing on this but then it's only when you zoom out that you see that wow this wasn't a bug but in the cont text of these two calls there is a problem right so zooming in and out and this is not sort of there's no zoom in and then zoom out it's not sort of a uh streamlined structured
process typically what works best for me personally is sort of doing this on a um I guess it just happens automatically you zoom in and then look look at the broader context and see what works we talked a lot about documentation but with the lack of that or if it is not enough there is also something about gut feeling right you over time you really get a sense for uh your intuition tells you that something is missing here or something is wrong hicup talked about the start and the end of life cycles critical follow the whole path usually it happens multiple times some flow something is
missing something uh didn't start well with code mock less Fork More Mess Around more depends on your personality some people like to do a lot of that some people you know prefer doing just looking at the code and you know just keep everything in the working memory of the mental state Frameworks and extensions explore see what works best for you a lot of the assumptions are really around preconditions and postconditions for functions or for statements keep thinking about that we talked a lot about coverage in terms of let's say your bug Bounty or in
terms of the scope but there's also leverage right and this maybe matters more in contest and Bug mounties leverage your strengths your AR talked about sort of leveraging let's say if you're really good at L2 or you're really good at um certain aspects of defi liquidations there are there are bugs that have been found where people have found you know uh something reported in one protocol and they've gone and really leveraged that across multiple protocols there could be Forks or similar ones zoom in and zoom out the other way of saying that is really dive in right and sort of step out take a break take walks take you know um any other breaks
whatever suits you right Pomodoro of your choice do that and I I really love this about I think Nat I forget who mentioned but the your should be underlined it does not matter what the four of us say or the 400 of us say but it's really about finding your tools finding your techniques what works best for you just because it works for one does not mean it has to work for anyone else prepare practice and patience that's that's the key and finally it's really about taking is TLC is just a acronym in
some parts of the world for Tender Love care take care of the code which is why we are all here more importantly take care of yourself so those were all the tips and with that we I think have maybe uh few more minutes for AAS so this has been sort of a one-way um monologue right or quadr uh but yeah any any questions I think there should be a microphone feel free to ask us we should have few more minutes and after that we will announce the quiz so do take a note of the quiz as
well there are some interesting rewards for that so Y no questions it's one there couple there next thing hi my name is John uh quick question is that I'm new to security I wish to pick it up so is there any resource that can get people started okay just to repeat uh so you're new and you're looking for resources I think the fact that you have come to BSS 101 is a fantastic resource um there is as of today I don't think there's any
dir of resources online so right so look look it up um I will maybe shill secum as one starting point um so do look it up it sort of evolved but there is I would say cyphon I think is a fantastic c a c Pat Patrick Collins has a good YouTube course yeah um he covers the basics and he goes into the evm as well and I think other languages like Cairo so really good like 12-hour courses or and longer uh rescues is another one uh by the way rescu is having a rescues Day on Sunday so if you're available I think it's going to
be a fun time thank you yeah so cyphon rare skills and there are numerous road maps and blog posts and articles online hey hey it's Sam here oh that's loud hey it's Sam here sorry to wake everybody up um but I was curious as folks who have been in the space for a while now how do you decide between going really deep into a specific vertical versus exploring some of the more kind of adventurous sides of of development right now I know fully fully homomorphic encryption kind of based chain Stark net so um each of you like how do you do the trade-off between
chasing something new and becoming an expert there versus just kind of going to deeper and deeper into something you already know personally I just play around with everything and see what's the most fun and see what I think um just in terms of like the knowledge that I already have lines up the most I think there's definitely something to be said about no shortage of different topics different things that you can learn um so my tactic is just kind of learn a little bit about everything and see see what sticks yeah I think there's a difference between like a professionally and just exploring so in terms of exploring uh
person I just go for whatever is interesting it doesn't even need to be web 3 related um but for like more the professional side like you're kind of bound by who's running contest bounties or trying to get audits so there are I guess like your more common D5 web three kind of things are going to be the the things you're going to look at most for me um it's primarily been ethereum smart contract security uh focusing lately focusing more on the infrastructural projects as opposed to
the latest uh D5 protocol or uh the next you know new shiny object so that's that's been my focus so it goes back to my coverage versus leverage right I mean there is so much happening in the space that one can endlessly hop from one to the other without really uh you know maybe getting your feet wet but really not understanding it well enough I mean especially a security res maybe for developers or for others that is an option but for security researchers you really need to go deep and understand uh anything really better than the developers and the project itself right so it doesn't give us because the uh the freedom to sort of just hop from one
place to another really have to go deep so that's that sort of a limiting factor but that's that's sort of what what I enjoy yeah uh for me I would say I am a heavy defi user so I think it's good to have the perspective of a user uh trying out latest D5 protocols and you never know when that knowledge comes into play so to give you an example uh back in D5 summer when me not even mean coins um all the food tokens were launching and then there's this like master shf and there's a sushi swap there's kimchi Swap and then you just start like depositing money because I'm in here for the tech and the money yeah uh so it it the the Master Chef contract like you start
reading the code and then you start realizing how it works and then you realize protocol start forking it and you're using it in various ways right so then that knowledge somehow comes into play because you start auditing or you start reviewing these contracts uh a few years down the road so I think it's like exploring and also understanding from a US users perspective how you can uh how you are using the system right and that gives you in a sense an advantage when you're auditing them yeah hi there uh this one's specifically for Nat but happy for others to chime in uh when you're writing notes and more around how you structure your notes uh so you go through with pseudo code and
say writing things per function would you tend to have a specific section just for invariance or assumptions or do you mix them amongst uh everything because it can be pretty easy to uh lose some of those important things amongst the mass of documentation yeah personally I create just a separate document just for the list of variants because I mean it helps to have it in code because the next time you go around through through it you might realize something different about it but um for like talking to developers and kind of syncing with developers in terms of like correctness of invariance I definitely put that in like a Google doc and share it with them um I think otherwise it would be a lot harder to
share in variance with developers um and kind of to Pro to get feedback um on whether they're correct or not sorry you have a question over hi I'm jonath uh in addition to that question um how do you make sure that you have like all the invariants um completed in your list or not not only completed but that the uh list of invariance is complete you're never going to be complete um I think the there's kind of a like you can be you can be as complete as possible within an x amount of time but I think um given time Box reviews given just the
time differential um it's it's going to be really hard for a security researcher to make like to make sure those invariant the list is complete I think as a security researcher my goal is to essentially bootstrap developers with like these are the invariance that I think are true of your code base um it's obviously the developers responsibility to go in make sure they're correct make sure that they are accurate um and then hopefully for a developer to continue extending that list and continuing to change that as their code grows um but I can say for certain I've never been in a position where I felt like the invariance that we've considered and and kind of thought up during a Security
review was 100% complete cool okay hi hello one we have we have time for only one more question so yeah hey this is no and uh you know everyone knows uh AI is is becoming uh very powerful uh tools especially when we build protocol when we coding uh so my question is uh relative to the the combination of AI and uh you know blockchain maybe uh we can use AI for our uh daily development and uh the security research so I have
two questions first is uh uh how AI can Empower you know uh security audit what kind of tools what kind of things you do with AI uh during the the uh uh security uh product and uh my second question is uh what's your uh recommendation for uh those uh defi Builders and protocols to uh use AI to empower uh there are securities and uh uh you know daily works thanks I can yeah so um AI I think we've seen a good use case is for turning out report issues so I think evom for
example he uses uh an AI to to help uh write out his report but of course then after that he does a manual review and uh makes adjustments as needed uh the other is for uh kind of like throwing documentation into an AI Bard and then you ask it questions and you get it to ask questions back to you so it kinds of uh enhances or refines understanding of the protocol and if you're unsure about something you know just ask personally I use cat gbt when I'm unsure of something I'll just like ask it um as when I I'm unclear of something or like help help me write out this issue and then I'll make some modifications yeah I mean just to add to that um I think there are multiple
projects in this space trying to leverage AI uh tooling right in all sort in the entire life cycle it could be for uh program understanding so in terms of you know feeded the code and ask questions about it um and of course like with anything else um hallucinations are a problem right so you can't just rely on it and I mean this I believe is a big I don't know how how bad the problem is but I believe um with all the bug Bounty platforms you know all the AI gener issues is uh causing a lot of spam right so it's sort of the downside uh but I I mean I think we're just scratching the surface in terms of how this is going to help um and yeah looking forward to see
where where this evolves yeah I mean it's very promising but uh unfortunately a lot of the AI approaches have been like hey I go like I put this smart contract in C gbt and gave me all the issues and then the contract is like the Dow Haack um this is like the weakest form of evidence that it can work um so yeah it's really cool could be really cool right now I think the main valuable approach is to use it for code understanding H not necessarily for like or llms in specific not necessarily for actually discovering the vulnerabilities on its own so more like the hybrid like working together uh form yeah and I
guess so one nice bit might be in invariant development like you can kind of work together to like you can come up with your list of invariant and then more quickly develop them in like in the various Frameworks so maybe set Foundry invariant as like you might improve your workflow uh there one thing though you also said like how could projects use AI um I forgot the name of the paper but there was some research into the code written by Ai and vulnerabilities introduced by the AI itself um and it turns out that there's some risk there as well where the AI even though you tell it to build
secure code um it's not always very good at doing so um so yeah I would be really careful with uh yeah asking your uh CH GPT to build a whole whole D5 protocol uh and then just deploying it and putting your money in yeah yeah that may lead to a whole class of sort of AI copy and paste bugs for programs that you know where where the training data involved buggy programs and sort of you know your co-pilot and other things sort of filled it up that way yeah I think we're out of time yeah uh we need to wrap it up because Lunch is ready so everyone please if you want
to have lunch you can go to uh rooms three and four is on the right make sure you have a response and yeah enjoy your lunch okay and [Applause] one mat has the volume okay good you're back no no worries it's fine oh they back off okay so we have uh we have the squiz uh feel free to take it it's very short I mean this is a typical secum quiz we call it races that's why you see that word it's eight multiple choice questions uh we have the most secure password feel free to take a photo go attempt it you have 16
minutes try to submit it by tomorrow and the top three well uh you know by by scures Will um win hopefully win uh DSS 2025 tickets so yeah if you want to be here next year with the free ticket feel free to take this quiz and test it out thank you [Applause] [Music] e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e
e e e oops is
it oh okay all right hello um so well welcome to the uh control Workshop here in in DSS um so basically in this Workshop what I'm going to to to try to show you is um sort of like the grand like high level picture of what you're in for when you want to use control and sort of what I hope that you get from this talk is basically the foundation of what you are going to be dealing with um when you you know when you start using control um we we have killer documentation for a
lot of features um so basically what I want you to get from this is just being able to go to this documentation and be actually familiar with the whole process and know what to expect so but first things first who am I I'm I'm Juan um I'm a verification engineer at runtime verification you know what control is from um and yeah we're we're we're a a formal me methods uh company um we do formal methods for for ethereum also for other chains um and yeah you should you should check out our work because it's very very nice um the way to get control uh it's you can just run this bash uh this bash command to install K which is our our
package manager uh for you know our Frameworks and just you know you can you can use control from there um and also there's there's a repo with uh with the examples that we're going to be uh showing in this in this Workshop um you are not required to you to get the to get the repo for for for this presentation but uh you can recreate the the examples uh from there so this is where your control Journey starts uh at this very moment and it starts with re Jesus or Foundry right so basically if you know fundry that's that's basically you know what you like
you already know how to write control proofs like that's that's because basically control proofs are 100% Foundry compatible um and so basically you can take any any Foundry test uh that you would fuzz over and then you can run it as a control proof right uh and you will be executing it symbolically instead of uh concretely and we'll see what that means a bit later so the way to basically take a Foundry test and then you know turn it into a control proof is you swap instead of Forge build you just have control build and then instead of Forge test you have control proof right and and these two commands basically do what you would expect them to do um in in Foundry to run you know to
run a test you need to prefix it with test uh with control we actually have two more prefixes which is proof that come from hbn which is another formal verification tool from for a and then we also have check which comes from halmos so this means that you know running writing you know control proofs also it's it's compatible with these with these other tools or you can also take these you know properties written for these tools and bring them over to control so it also has like great um compatibility features um also we as you would expect with something that uh a fer test we also have compatibility with cheat codes we also have our own cheat codes so
besides um supporting fundry cheat codes we also have our own um but also recently fundry have have have included some some of which were our cheat codes initially into into their cheat code suit um so basically the for the compatible funded cheat codes you know you get the mostly the the most execution related cheat codes the way that you know allow you to manipulate evm State and so on um we don't have 100% % of like the maximum amount of cheat codes that Foundry has more the ones that we don't have usually it's because we haven't like see that we need to use them so if you're missing any um feel free to reach out uh and and you
know we'll we also incoming them based on you know what they what our users uh what our users need so yeah feel free to to just reach us out um also we have our own like cheat codes which are because we're doing symbolic execution rather than concrete right so we needed the own type of cheat codes that was uh you know important for symbolic executions um so yeah we added them and one of the reasons why we initially have this you know instead of having a test prefix have a proof prefix is because if you have custom cheat codes they won't run as a Foundry test so you also you want to separate them and not to Break um you
know f test suits so with some of the cheat codes that are own Foundry won't run but this is big of an asies because you know fundry recently added some of our cheat codes in particularly these are the new cheat codes that were control inspired um this set arbitrary storage copy storage mock function and then this random youu INB address and bytes so the control equivalence is not exactly the same cheat code in the sense of the naming but what it does it's sort of equivalent and bring brought to the realm of of of fuzzing so set arbitary storage for us it's symbolic storage for copy storage and mock function is the same and then for the random we just call them fresh because in in the
symbolic context it does it's not random itself uh it's just a fresh variable so basically what set arbitary stars does uh in case you don't know it in Foundry it just sets you know a concrete fixed number uh for any uninitialized rre slots um of a given address um and for us it sets the entire symbolic storage uh so sorry the entire storage a symbolic right um copy storage it does with what it says it just copies the the storage from one account to another uh we also support copying transing storage uh when when needed um and in Foundry as a c you you cannot use uh both copy storage and set arbitary
storage um we also have this mock function which is sort of like a you know a mock call but on St a bit so M call would the cheat code mck call would just you know swap a function call with a in a specified return value in this case mock function what it does is mocks the execution so it will swap the mock the the call with uh what you can consider a model of the of the function that you're mocking uh and so you that that is useful if you want to if you have very complicated function and you want that you know that you want to execute just you know sort of like a model or summary of it uh but you you still want to run it not just you know get a concrete return value and then we have this random which is just uh in fund
just a new fixed uh value and for us is a fresh um symbolic variable so this uh these cheat codes are not yet implemented in Foundry uh they are sort of in the pipeline so these are chit Cod that we still have uh which is sort of for funer you have expect call which is like for us expect regular call but we we wanted to also have some some sort of more granularity where we're writing our tests so in particular we have these calls which with the cheat codes which is which are kind of you know self-explanatory um so basically up to this point why do we need to be so symbolic right like we have like you
have found which you know fuzes concretely and so on so why do we why is there need for symbolic reasoning and well a bit the the the reason behind it is that you know with concrete like the state space is just too much big um so with with symbolic reasoning it allows you to actually explore basically the totality of it if you if you if you do it correctly and or at least a way bigger amount of the state space and to ensure that your function you know has been uh as thoroughly explored as possible and so for in instance here what you this could be like just a Foundry test um but you know what what
executing it symbolically allows us to do is to make sure that there is no value that's being tested that if this passes you know there's no value that W that will um make this test fail whereas with concrete execution if if you're if you're fuzzing you know you you will never get this level of assurance um so what is symbolic execution in this case right so as we said for concrete execution basically you just take uh concrete values you start with concrete values then you execute and you always get sort of a concrete result whereas with symbolic execution you can think of it as um executing it as if it were variables from like a math equation right so you
start with symbolic in this case from for instance if you're trying to somehow verify the behavior of the transfer from function you will start with um symbolic values for for for your pre-state then you will execute with some symbolic Val values and what you will get is an execution brand as so yeah an execution tree where each branch basically summarizes a lot of behaviors that can be done in like a lot of concrete tests and in this case you just get like for instance in this example like what is what if in the transfer from what is from is different from Two and what if their equal and then what you get is like a mathematical evaluation of this and sort of like a symbolic summary of what's the behavior of your function going to
be and so as we said um symbolic execution you're executing but in a symbolic way sort of like just think of it like variables in a math equation um and you start from a from a concrete from sorry from a symbolic State and you end up with a bunch of symbolic States each of them symbolizing where can function n um and so taking all one step back it's like so what is formal verification right um more broadly formal verification means like you assert properties of your code which is called specifying it which in the case of control you can do it uh with a Foundry
test you have found property test and then you prove you know that your code actually satisfies your specifications there are a lot of techniques to do this like to take some specifications some blueprint of what your code supposed to do and then doing some mathematical reasoning on it to make sure that you know your code actually follows These Blueprints symbolic execution is just one of them uh where we execute your code you know as we said symbolic parameters then you get all this branching and basically you just get like a a a like what's your function actually doing and then we check that for every possible path execution path that your function can take um you know your specifications your blueprint uh is complied
with so it's it's also the case that you know there there are many techniques for for doing formal methods formal verification um and and they there's a spectrum right like they they vary in the in the degrees of automatization and they also vary in the degrees of which is the the problems that they are able to solve so meaning what what's the kind of statements that you can prove um and usually as a rule of thumb you know the more complex so sorry the more the more automated appr proov is or rather the other way around the less automated approv is approver is sorry um a tool for for doing uh formal verification usually this this translates into the ability of of proving more complex uh
problems um this is also like sort of like a rule of thumb but um basically there's this this spectrum of the most Auto the least automated Ur usually the the more like General problems or the more complex problems you're able to tackle um it is also true that you know the more automate automated you are the the the the bigger the the easier to use it is right and especially for the for the kind of problems that it's automated to solve uh these tools are are really fantastic for for just ease of use and you know um yeah just to to get you going um and I wanted to give you some like examples
of of how how like how does this different sort of proof systems work right so basically you have what interactive Theory improving which is like the most automated thing that you can get which is like Mo mostly manual and you also rely on you know constant feedback from your tool to let you know where you are and it requires a lot of user input and usually the the learning curve is quite steep um and then you also have automated reasoning which usually doesn't require any any interaction hands automated um and it's also usually the case that you know you don't have any insights into what is the proving process so it's sort of a bit like a blackbox in the
sense that you you query it for a proof saying I want to prove that my function something um and then it will say yes no um but but there isn't as much insight as with the uh you know interactive uh tools so for instance here's an example of an interactive tool um this it's not very important what it says just so this LM for is what is called an interactive theor improver and in particular this proof proves that you know if a graph is hamiltonian then it's connected we don't really care a lot about this but the thing is that with interactive theor provs you can get as far as into formally verifying virtually any type of math like not just you know programs and
functions but like literal theorems about very complex things um this is what a proof looks like there like like the statement is like the first and second line and basically the user needs to needs to feel every other line here which it doesn't look very intuitive and the type of feedback that you're being given by the machine while you run this looks like sort of like this so you can tell that there's a there's a somehow a steep curve into learning this sort of stuff it's also very rewarding in the sense that it allows you to go very deep and prove like you know arbitrarily complex properties about math or your code or you have it then we have um automated TRS in this case just with halmos and
this is how one like how an automated proof looks like in the sense that you know you just run it and it says if it passes or not um if not it it gives you a coun example it is also true that with automation it means that you can get unknown results uh meaning that the tool may just you know run out of time and saying you know I I try to prove this automatically you know there's some bounds of time because the tool is not going to be running forever uh and if it doesn't find a solution to it it will just say hey I didn't I didn't just find the solution for this um and then I want to give an example of control because control is sort of in the middle uh it's it's automated but it's also interactive um so this is one example of what a
control proof looks like uh when when it passes so it just sort of like it looks like automated like you just run it and it passes or not um but we also get feedback which is one of the key principles that you need for for an automated procedure right so in particular with control the type of feedback that you get is this this this tree that's that's made all of all of the possible execution paths that your function can take in particular here we're seeing a branch uh where it tells you which is the path constraint that you're that that you're traversing right so for instance here it's telling us that you know Y is different than zero and that X that why it's less than you
know maxu 56 so there's no overflow in the multiplication and so on and so basically you know like okay I'm executing the function in this context and what we see here are nodes uh so basically the nodes are snapshots of the execution at a given point uh and in this in this noes uh what you get is like the full state of of the or formalization of the etherum virtual machine so you get this sort of a HTML looking configuration and here it's contain the all the information uh of formulization of of of evbm so basically here you have um in in we go like with cells right and so the Kell for instance
it's or formalization of the execution uh of evbm and then you have things like this chedle uh which we default to Shanghai but we also support Cancun and changing this is just you know one one command flag away you also have the output you also have you know color call data and so on war stack local memory so basically everything that you would hope for uh when executing like okay what's the state of uh what's the state of of my smart contract when I'm actually running this function and then we also have the interactiveness part right um so because here so the way this goes usually it's like you execute it then you inspect a bunch of states and then you say okay
this is telling me that my function is behaving like is and then you can tell control to say okay now I require you to reason about this in this in this specific way and we do it uh through what we call lemas um we'll we'll go over this uh in a in in more detail later but this is basically what what interacting with with control is looks like it's writing these files that then control will will parse and then we'll we'll rason with uh taking into account what we wrote um here's also sort of like snapshot of of you know this is a non-exhaustive list of formal verification tools available for the for the ethereum ecosystem um but yeah we we luckily in
this space we are not short of tools and and there's there are fantastic teams uh working on on formal verification for this so I I heavily encourage you to to take a look at every tool because you know as we said there's like a spectrum of automation versus versus versus ease of use versus you know kind of problems that you can solve uh and so there's there's like there's one tool for each job I would say or at least you know for the kind of of verification that you want to do so yeah definitely check them out um that's nice but you know this is a workshop so let's let's get some some work done uh we're going to be verifying some stuff with control um so
first of things first I want to talk about Harbor requirements because control is quite resource intensive and we've had this cases in the past where it seems like control is crashing or failing but it may be that it's it's because of of lack of resources so we require a minimum of 16 gabt of memory for for things like building and so on um there's some caveat like if you're using uh this windows subsystem for Linux I think it by default only allocates like two gigabytes to it so you should like you should look that up and make sure that you have if your machine has it at least give 16 gabt of ram to it and same with doer containers I think in Max it's also cap like a 2 gigabyte or something
so just make sure that you you have these requirements like set up um and also for running proofs in parallel as a rule of th we like 8 gigb of ram per proof this is not like you can experiment with it your computer is not going to burn or anything um but yeah this is sort of like like what we look to uh usually and so this you may you may feel if you've ever try control you may feel a bit uh represented in this picture in the sense that there's a lot of options and there's a lot of things that you can tweak with it and it can be a bit overwhelming at the beginning so I'm hopefully trying to give you some uh some clarity into into all of this so
this is basically how the interactive interaction Loop with control looks like so you would start uh right at the at the build stage right you first build then you prove and then you inspect right so you build to well first be able to prove but also to include new lemas this is this is uh one of the reasons to keep rebuilding stuff and then when you prove basically you will produce what I said what I showed before this uh this symbolic execution tree and basically there's like a su Loop there in which which you inspect the symbolic execution tree and then you sort of you can manipulate you can you know like you can say okay you did something weird here
and I want to zoom out on zoom in on this and so there's this there's this cycle in which you know you prove you produce your symbolic execution tree which is like the summary of how your function behaves and then you can inspect this summary that control produces for you um and and just sort of gain more insights into what's happening and then out of those insights that then you may be wanting to write more lemas uh to then include them again and proving and this will make some sense um in a moment but this is yeah this is like high level how the you know proving interaction works with control so yeah if you just go and do like control build help or control proof
help you will be bombarded with all these options and sort of if if you try to sort of um understand which ones are the ones that are more useful to you it's again can be a bit overwhelming so let's start with control proof oh sorry build um and see among all of these what is really important for you as a user so basically the the the important options revolve about you know including auxilary including lemas basically excluding some if you want to and also regenerating uh K definitions uh which you know this is used to include neas so basic basically to include auxiliary lemas we have this flag auxiliary lemas to control build at the
bottom you can see sort of the command that you would need to put to to to execute this this step um these auxilary lemas is just things that we have encountered uh and you know working with the tool and we found very useful so this is just also sort of if your proof is not if not working from the beginning this is something to try right away because this enhances controls ability to reason um then you also can include uh your own lemas uh we do this with this you know require and then a path to your K file and then the model that you want to require this is not important that you like memorize any of this it's
just like so that you know how it looks like um then we also have some catch Lamas that are included by default in control um you can also exclude them but you know they are basically like working assumptions on how the catch act should be basically we assume injectivity and we assume some Collision resistance from symbolic values uh these are not mathematically sound uh and this is why we include them as a separate part like these are not part of like our core semantics of ebm but you know these are like working assumptions that we need to do uh in order to be able to to reason effectively about uh about you know evm code um and then you can also just regenerate K definitions in case you
include some lemas with regional recompile so this is a bit of how like the the full control build um command looks like and also we have control proof so again control proof has even more uh options than control build and so it can be really daunting to to just go about it um again the the relevant options uh are for proof execution tricks so it's just getting you know zooming in into the execution trees uh doing some Loop exploration behavior and also so to to increase the performance of control uh to get you know more detailed uh execution trees remember we we have a node so we so an execution trees is
basically it's paths based on Branch conditions and then we can specify when do we want to create a node which is like a snapshot of the entire state of orm while executing your function and so we have a lot of you know rules to create uh new nodes uh you know with have max depth which basically means after doing X steps of execution just make a snapshot of whatever you have then we can also specify when do we want it to break in terms of for instance AVM op codes either every AVM op code every jump ey we also have now jump uh we can also like if if you say like you know I want to know where I'm jumping to a
function or when I'm jumping into a loop or whatever you can break on jump I will allow you to create a c C where you have snapshotted every time you did something like that also on storage and and on cheat codes um you know we we also can change the loop exploration Behavior so one thing that's in control by default we don't bound Loop execution this means that if you have like an unbounded Loop uh you know you you can get an infinite uh exec a potential infinite execution tree uh and the way we do it we we allow we allow uh bounded Loop reasoning control via this BMC depth um command where you specify how many Loop and Rollings you want to
get so basically you will enter a loop and then you will execute it the amount of times you specify and after that it will it will just uh conclude the proof and and and give it as as as passing um and we can also specify looping variant which is sort of like the other way of tackling Loops which is instead of just you know rolling a finite amount of times you can actually specify what's the expected behavior of your Loop and then control will take that into account and then as per control 1.0 uh which really released uh some months ago we also have this optimized performance
flag uh which will just make things faster and you don't have to take uh you know you don't have to twe some parameters uh uh yourself it will just get the faster execution running where and it will also do like parallel Branch exploration uh which you know you can set the number of how many branches do you want to explore concurrently again this depends like the number of branches that you can explore concurrently will depend on on you know the the hardware that you're running this with but yeah just keep that in mind okay so you just control proof something and it passed or failed um now we need to to inspect what control uh gave us back right so we have
basically two exploration commands one is control view K CFG which is a terminal UI uh interactive viewer where you can click on the different nodes and see the different uh State snapshots that it took uh and there's also a control show with just plain CLI output um and also uh we introducing K as a service which it also gives you a web view of of your proof and it's it's a very nice web view um and and so yeah more on that also later um once you seen what your proof looks like you can also do some manipulation um which basically means you can remove notes you can you know say I don't want
to explore this Branch anymore um we'll see some some more of that later but I just want you to get with like the main part I want you to to go with it's like you really can inspect everything you want about your function execution with control then you can you know manipulate what the snapshot looks like um and and and start reasoning from there so maybe you're like a bit like this after you know all this all this Mambo jumo so just remember what we're doing here basically just these different steps where we're either including Lamas they're they're we're we're proving and then producing this this uh symbolic execution rri and then we're
manipulating them we're expecting them we're doing a lot of things with them and out of all that interaction we can write new lemas uh that will make or proofs Advance further okay so now let's let's apply the verification cycle uh that we just shown we're being we're going to be working with um with this example uh which it doesn't look very super interesting at first but it will tackle the whole thing um um and and it's a very I think it's a very complete example as in how is the complete usage of control looks like right so this basically is just you know adding numbers from I from zero to to
n um so we start with n then we have these two these two variables set to zero then we go into this Loop that you know we just add one to to I and then add I to result and then we return result right so what we expect intuitively is that you know s to n of of n it's actually the uh well adding uh numbers from zero to n which coincidentally this this has a very nice mathematical close formula which is this one uh we won't be proving we won't be showing this in the proof of this statement in the talk there's a very nice post that that um that rul here recently uh did uh about the formal
verification on on loops and the proof is there so I encourage you to go to our blog post page and and find it um and so after looking at this we would expect that you know our specification for for the prove some to and look something like that right so with this in mind we can just build it and then just try to prove it and as I said before control by default doesn't bound any loops and and some to end is B basically just one Loop and so what we would get if we just execute that we have here it's something like this uh so this is the the execution tree sorry the the symbolic execution tree that I was talking about
earlier uh so basically you just get this this notes which are just snapshots of what you have and then basically here you can see a jump ey this so the thing also in control is that you're you're working with evm bite code so even though you write your testing solidity what you're actually very is what the what your what your code is actually being compiled to um so here we we see that we are entering the loop uh with this with this jumpy instruction and we also see that we're checking if n is less than zero so basically what this is checking even though we we this is not exactly the condition that we put in but the compiled code what it's doing is checking should I exit the loop or
should I continue and enter the loop right and so we checking is it n less or equal than zero so should I just exit and then control just branches right this is symbolic execution so then control just says hey I don't know if n is less equal zero and is a symbolic variable so let's just suppose on the one hand let's just suppose it is and then if it's less requal zero it just exits the loop we can see it exiting the loop here and then it just says okay then I I just finished so for this Branch you know I do get to a successful State and your test passes and then it goes on and says okay what if actually n is greater than zero then we enter the look and then we execute a bunch more and then you know we do one iteration
and we say Hey Now what if n is less than one then if if that's the case then we just exit and if it's not the case we're still in the loop and then control will do just will just do that again with two and with three and with four and it will just not stop why because we have not we are not bounding Loop execution here so by default control will start to create this potentially infinite uh execution Branch right um execution three sorry uh unless we at some point we stop it but if not as you can see it will just get bigger and bigger and bigger here is where I stopped it but and so how do we go about this um does that mean that we cannot verify this with
control well luckily uh what we have here is that we can add BMC some BMC depth so we can tell control hey at a some given you know depth uh just accept the proof like I just want to execute this symbolically and you know if it has worked for the first four iterations let's just assume it will work for the other how many it will it could have right um and so with that it will pass um so I executed this proof with BMC 4 and we want to see how the how the the execution tree looks in this case which it will look basically the same as what we just saw but at some point again it's here it's branching then we enter the
loop and then it says oops and then it says yeah sure everything is fine and then we will do that several times and then right at the bottom exactly and then we get here and then it's like well is N More greater than than four should I enter the loop and then it's saying well here I'm assuming it is but I would be entering the loop a fifth time so that's out of our you know that's out of a bounds and then it just cuts it and say okay I give this Pro I I for every iteration that I entered you know I completed I successfully completed the test uh in this case I'm just going to end the test here because you told me so and so that's all that's fine uh but for instance what happens if
we have say a malicious Su to n and by malicious I mean like what if you know we're executing the loop but it says huh if I'm greater than four I'm just going to give you an incorrect result right uh well the thing what what happens here is the same basically you will you will if we I think I have it here uh if we run this oops sorry about the live demo
thing uh yep well you can see here if you run it uh basically it will pass uh you will have the same amount of nodes um and it runs in basically the same amount of time and so here what is happening is that the the you know the the the behavior that would make this proof fail it only happens after a certain amount of iterations and so how can we basically go about this right uh yeah if we executed with this basically we'll just uh succeed uh so how can we solve this well we can solve this with with uh with looping variants so looping
variants are basically their properties that you know are supposed to hold before the execution of a given piece of code and after the ex execution of a given piece of code um you know invariant can also be trivial properties uh because something that holds before and after doesn't really need to be meaningful about your code but you want this to be something actually meaningful uh about your code so basically a looping variant you should craft a looping variant in the sense that you should craft a property that captures what your what Your Loop is really doing um I will also say crafting Loop inv variance it's a problem that is arbit probably hard like this this is this is this can be very quite a challenging uh
problem to face in the sense that you know for instance if you had a very dumb Loop that it just computes you know you just give it a number and it computes the N prime number like coming up with a looping variant for that will basically Grant you the the novel equivalent in mathematics so it's it's really like it's a it can be a very challenging um Endeavor but you know control support it and and there are ways to to sort of automatically or Prat pragmatically come about with looping variance so let's just start forging the intuition here on on how does forging gooping variant for this look like so when we start the function we basically have that result
is equal to I which is equal to zero which coincidentally it's also equal to you know the closed formula that we hope this function to be uh equal to and after executing the the loop we would we would get that I is equal to n and then hopefully we would get that the result is equal to you know n * n + one divided by two this is what we want to actually know like this is our intuition but we don't know and so these are sort of the loop invariance uh recipe when you're looking at solidity code so you basically look at the Loop head see what you expect the state to be then you execute the loop then see how the state is updated
and then you sort of want to generalize that into a property that captures you know what what is the what are what is the state updates that your that your Loop uh ends up with this is for solidity though um for evm you we have to do a bit some more extra work uh because we first need to identify where the loop head is uh because that's not that's not um you know super trivial to do uh when breeding U bite code and then we just again sort of inspect how the state is see how it's updated generalize it it's very important with control once you come up with what you think is a
sound looping variant control allows you to actually prove that your looping variant is correct and then basically you can include this looping variant as extra knowledge to control to say hey my Loop takes states that you know have this sort of form and after execut in this Loop it transforms it to a this different state that has this particular form and in this way what you're doing is actually you're you're effectively summarizing the actual behavior of the loop and you are sort of executing it to completion which uh you know it it gets rid of of just executing a a few iterations you're actually encapsulating
the entire behavior of the loop in this uh using this invariant approach right so first we need a word about lemas because you need to understand how to write a bit of you know K which is what control is based on in order to feed it lemas and so basically very quick um the files you know starts with some requires which you know you in here we we import a formalization of you know how fer execution works and how evm execution works then you just have this module which where you will have your your Lamas which are like this reasoning bits that control takes to enhance its reasoning power um you import some modules and then basically there here's
like the meat of the of the file which is the rules the rules sorry or lemas um so a rule basically just has the signx rule something requires something and then simplification for us a rule is something that that is a rule that has the attribute simplification but yeah basically just rule then you just write your rewrite conditions this basically means you know if you start with the left hand side of this rewrite in this case Bol toward X you you will rewrite it to whatever is on the right hand side so this is the rewrite symbol so this tells us that you you you start with this state and then you will end up with this other state then you can have a requires clause which basically is just
apply this you know this transition between two evm states just apply it only if the condition that goes after the requires Clauses uh is fulfilled you don't it's not necessary to have a required CLA but it's there in case you need it and then it's just the simplification attribute which is sort of like a particular type of of re rule that we have great so um let's prove the invariant but first let's see how this looks so we want to in this case we want to First inspect um the configuration that control has given us right um so when this loads we sort of go
here uh just as a as also a note um we executed this if you remember from way before um we had this break on jumpy instructions which basically tells when you are doing symbolic execution and you face you know a jump ey I want you to create a node which basically a note here is just I want to snapshot I want control to snapshot whatever the state is here for me to execute it and we did this because uh since we're entering a lo lo start with jump eyes so basically we just scroll down also sort of like warning sometimes you will have to aggressively scroll down or up due to the you know amount of
information that controls gives you but that's just something to get used to and I think it's actually a pretty good thing so here we are um note 27 we are at a jumpy and here we are splitting so here we're branching um tldr this is our Loop head really as we saw it's seeing if n is less or equal than zero and if it's if it's not it will just exit the loop and if it's if it is then it will just enter right so I I executed this with BMC depth 4 and here our goal now is to see okay I have this jumpy here uh node four uh and this is the very first time I'm entering the loop and then if
we scroll the way down we can see yeah this is where it bounded this is the last time it exited the loop uh here this is the last time it exit it exited the loop um and so basically what we can say now is okay uh give me so the the way we're going to come up with the invariant is we're going to see which are the state changes that happen between the first time we were uh we were entering at the entering the loop the first time we were at the Loop head and then the last time that we that we let control execute the last time it exited the loop so the way to do this um is via this
uh it's via this uh control show uh node Delta so what this will basically do is it it will take to notes and it will perform the difference of what what's what has changed in the evm state between this node and this note and if you notice um we're doing it with Note 54 which is the first note that's actually jumped out of the loop um so if we just do the no Delta thing it will it may take a little while to just load but it will basically give give us again the the entire configuration and then at the very
bottom of it it will give us a configuration that contains the state Delta here so it contains basically what has changed between node 27 and not 54 uh and we can we can look at it by looking at these at these arrows so basically it said okay what what has changed is you know in the K in the casell which basically is where the you know the evm code is executed you went from this jump ey on this condition to basically just jumping and then if we scroll a bit down everything else stays sort of the same uh and the only thing that changed as
well was that in the word stack you know we started with these two variables and then we sort of we are we ared to two and then here to three and this is for actually for for be for the second execution so once we see this our job is to say okay we we've gotten this State updates um what is the general form of this right uh and basically that's how you you can craft an invariant with control you can just come sort of come here and say okay you know we we know we were we were here and then we jumped here that's concrete and then so first of all what we're going to do is we're going to well first craft the thing uh and then we're going to prove
that what we craft is correct um so yeah basically we're just saying you know we have this sort of this state and then we're just going from here to here and then which generalized what we saw oops we generalized what we saw here into a more abstract formula and just saying you know from I I go to n and then from this close for form we go to this other close form the thing is this is a claim so maybe this is too detailed but what I want you to get to to remember of is this is a claim of what you're doing is you're crafting uh a state difference and then you're actually proving that the state difference holds FS um and this is done via this this this claim
instead of a rule uh we're just saying yeah this is this is how you know the K execution cell is going to to to differ to change um there are some stuff that uh you know we want to keep um just to get to keep the rule uh actually uh well provable in the case in the sense that you know this is how we executed this program um here is the the the main let's say source of reasoning that you want to have so the main abstraction that we're doing is coming from what is written here to what is written here and and that's that's where the challenging part of crafting looping variance comes
which is you have to you have to understand your code you have to uh reason about the properties that it has and then you you sort of go from this concrete um difference to to the general form that it should uh that it should have then we have uh the same PC that that we were executing with and then you know some more stuff and then some some well forness conditions and the thing is what we're saying now is hey this can be turned into a rewrite rule so this can be turned into basically just telling control whenever you are at this program counter whenever you are facing you know the head the
loop head which is this thing thing that we have here just rewrite it to this and then you know the general behavior of my Loop is going to be this transition right and with this claim what you're actually doing is telling control prove me that this is correct so this is not giving the user like you just write whatever and then control will just take it you're just able to you're actually able to take control and say just prove that this state transition is actually accurate and that it works um and then you just you know you you can translate this into a rule once you have proven it correct um which basically means just taking a bunch of other constraints and putting it in the button but basically you end up in a
loop in which you know you actually like you have the state transition and this captures the actual behavior of of the loop of the of the while loop that we were facing with um once you do it uh you can actually prove the statement without any BMC depth so it will be capturing the loop behavior in full um and yeah and that's how you that's how you basically can verify a loop with control um we this we have used uh in in in our engagements uh because also there so we have been dealing with a very like on the face kind of loop um but also for instance
there are some Loops that are inserted by the compiler um not with the recent with the mo with the latest one since we have now M Copy but it was the case for for I think it was from solity 0. 8.24 previously if you had like a bytes memory argument you will like the compiler will insert their a loop that you will need to reason about uh and so for instance this this lets you reason about it uh in full generality so I hope you you you are excited to try control I try to show here uh from you know going to from the basic use to actually show you an advanced uh
example of how of how to use control uh we have I think we have killer documentation on this uh you you we we also you can also have control on your CI um so please feel free to to to go to the documentation read it and we're also very responsive and active uh so if you want to get in touch with us uh feel free to come to our telegram channel to our to our Discord uh we're we're more than happy to hear from from from our users and so thank you very much for attending this [Applause] talk for
I didn't get the memo on the getting the adapter it looks like we need a USBC to HDMI yeah awesome thank you okay
um I can just stick oh yeah I'll just just use the yeah okay can I get my notes here yes seems like it shows that up there too though okay yeah
awesome perfect thank you okay hello everyone I am Elliot fredman and today we're going to be talking about secure smart contract development um I'm the founder of solidity Labs we're a boutique consulting firm and uh we build smart contracts uh for our clients and we have a very keen interest in security and so really excited to share um some of the stuff that we've been working on with you guys here today okay so high level uh what we're going to be talking about um first we're
going to talk about the different types of um smart contract systems and the types of governance that that come along with them we're going to go over the secur dir stack which is the types of tools and testing methodologies uh processes and procedures that we can use to find bugs we're also going to go over blind spots and how they emerge and how we can remedy them um and that will be around where bugs are commonly missed and then we're going to do an exercise so this will be interactive where you guys will be able to pull down some uh some code um um and uh use use some tools to to find these
bugs okay so it's it's important to first start off with categorizing the different kinds of smart contract systems so the first kind uh of system is immutable so this is one that has um no admin Keys No upgrade ability um there's you know very little there's not going to be any tooling around governance because you know there there is nothing to govern there's no trusted third party um a good example of this would be like amm contracts that don't have any fee switches so you could talk you could look at the Unis swop Factory contract you could look at router contracts where you know different
actions are bundled together then we have governance minimized and so um these uh these these systems they have a few knobs and dials that governance can turn um you know you definitely would need some tooling around here to generate your proposals and safely parameterize the system so you could think about like the fee switch on Unis swap or um the fee switch on Moro or Oiler where they can set the fee um but then the rest of the system is immutable so you you can't actually upgrade the smart contracts the Third Kind is a governance heavy
system so in a governance heavy system the um the governor the governors or whoever this trusted third party is they can upgrade the contracts they can change the system parameters um and to do this safely there's you know there's a lot of times there's sharp edges uh with these kinds of of code bases so uh an incorrectly parameterized uh system is um you know is can cause a lot of money to be to be lost so lending markets I think and rollups are really good examples of these kinds of systems because uh you know there's a lot of knobs and dials there's a lot of like different delays or you know collateral factors uh
interest rate models um that have to be set and these also tend to have upgradeable smart contracts where the admin can can come in later and and make changes to things okay so now let's talk about the security stack so um the most the hardest to find um I guess the most pernicious bugs they're they're always the ones that um no one is looking for and when you're building uh contracts a lot of blind spots will emerge because um you know let's say you're writing a new amm and there's some really complicated math
formula so you're saying okay let me make sure that okay the math here is like bulletproof it's super solid there's no issues and so you spend all your time writing tests to make sure that your math is good um and because you're doing this um uh you know a simpler bug might just kind of slip through the cracks because you're spending all your time uh on this one thing that you think man this is like where the bug is going to be um okay I guess I just skipped out here okay so there's um I don't I don't it's kind of skipping ahead
now um okay right so then also let's say you're writing a uh lending Market uh smart contract then you know you're going to be spending a lot of your time on um liquidations or reward logic or interest rate models um and then there's going to be other parts of the system that you're going to spend less time on and again that's another place where um blind spots will will manifest so we can think of um security for smart
contracts as a stack so we have all these different kinds of tools and techniques that we can throw at a smart contract system to try to find bugs and at the very bottom of the stack we can see um we can see the cost of finding bugs so uh we can write fuzz tests unit tests integration tests um we can run static analysis and these are the this is like the cheapest way to find bugs so you should invest in making a really solid test Suite because that's going to you know that's going to let you you find all these things um and find the bugs as as cheaply as possible so once you've exhausted like the really easy way to find bugs um
you're going to go and say okay well how let's let's get a little deeper and so then you'll be going to something like um symbolic tests so that could be um helmos that could be hvm there's a lot of different tools that allow you to do symbolic testing so that will you know give you certain um it will tell you certain things about about the contracts that maybe your fuzz testing or your unit testing wouldn't find then you can go on to you know formal verification and you could use a tool like the Sor approver or uh kevm or control and those would would you know find really really hard to miss bugs um but they're definitely a lot more expensive to write
a extensive um Suite uh formal verification it's like specification of your smart contract system than you know other other testing methodologies we also have code reviews and code reviews are really great for um almost just like rubber ducking things right where you say okay you go through the code line by line and say okay what what does this code do what are all the assumptions what are the Upstream things what are the downstream effects um and so those are great obviously it takes you know more time to coordinate um Cod RWS um then we can go on to audits so audits are going to be yet like an even
more expensive way to find bugs but definitely you should definitely do that but that's like comes at the end of the development uh life cycle and then uh we we get up to bug bounties and so the bug bounties um this is the most expensive way to find a bug in your system you should definitely have this um it will give white hats an incentive to try to find uh bugs in your system and then not pictured in this uh diagram but it it does happen are um you know black hat hats where and that's the most expensive way to find out that you have a bug uh is to get all the money stolen so um it's definitely worth investing to make sure you don't get there okay and so one thing that um
is everything good okay and the other thing is um giving yourself space and time after you've um finished building um and you're you're you're a code freeze or you've you've stopped you know major
Feature work um oftentimes when you when you've really been like just throwing your head against the wall against a certain problem or a code base for a long period of time you're going to be blind to the bugs that you've written and so just you know giving yourself a weekend off off or like just some time where you don't think where you like like consciously don't think about the code you've just written um we'll give you the space so that when you do come back and and you think about those problems again then you'll be able to you'll be able to you know find bugs and come at it with a fresh perspective that you wouldn't have if you were just you know constantly um trying to find find the issues in the system um and this during
that period of time when you come back you can look for gaps in test coverage you can look for you know um yeah things that you missed okay so this is a quote from tenet um no one cares about the bug that didn't get exploited uh only the one that did um it's the bug that didn't get exploited the danger no one knew is real that's the bug with the real power to change the world and I included this in the presentation because I feel like security for the most part is a very thankless job um because when it when it doesn't work you don't see it and then or when it when it does work you don't see it but then when it doesn't work uh like everything has gone uh horribly
wrong um and yeah so that that kind of leads us on to um the bugs that we will um the bugs that that regularly get missed um and so I think that a lot of times when we when we're talking about you know building new contracts we'll you know we'll be testing like all the new system components but kind of the the parts that get overlooked uh often are your deployment scripts and your governance proposals so um you know usually deployment scripts don't have tests so
this just means like there's basically uh just less less eyes on things in in general and less less rigor than the rest of the codebase and I guess in thinking about this you know if if someone submitted a PR and had a whole new you know a whole bunch of contracts and they didn't test it you would say well wait a second you need to write the tests but somehow when it comes to deployment scripts uh we don't apply that same that same logic which is not good and I think the same thing goes for governance proposals so governance proposals can be parameterized and upgrading and moving things around in these systems that have all this money at rest in them um but often times you
know we and we've actually seen where you know a governance proposal uh is not malicious it just contains a logic error um and that logic error manifests um in in in the system shutting down and not working as intended so I think it's very um important to test both of these things and I think also one thing to call out is that like earlier stage projects um you know if you're a later stage project you have the the budget you can go hire security researchers and they can go and review all of your governance proposals so that's good but earlier stage projects often don't have that um you know don't don't have the resources to do that so it's uh it's
very important that you that you test these things okay um wait can we transition the slides back to my machine okay yeah okay so now we're going to give um a bit of an overview of the um Forge proposal simulator so uh FPS is a um a tool that's built on on top of
Foundry um it offers developers a a standard interface for creating their deployment scripts and governance proposals and we treat um these two things as one and the same because a governance proposal might deploy a new smart contract um and then you know wire that into the system or up upgrade a contract um and this framework makes it really really easy to uh test do integration tests on both your deployment scripts and on your governance proposals so I think this is like a a really big uh unlock for for projects where you have like governance heavy systems and you're moving around a
lot of knobs and dials and you're upgrading a contract here and um turning a bunch of different knobs um so it it lets you really easily connect your uh integration tests into your um uh into your governance proposals and so then you can say oh I already have written this huge integration test Suite um and then with that uh integration test Suite you can you can test you can run the integration test Suite uh after the governance proposal is applied so maybe you have like a bunch of invariant and a bunch of like States the system like shouldn't be in or a bunch of behaviors um that You' expect users to take and then you can see okay if I do this
governance proposal um are these invariants you know are they still true and then are these actions uh are they still like can users um still take them uh other other features are we allow um we allow State diffing so we can we can give you a full printout of everything uh and all those different contract states that changed including like erc20 token balance changes uh ether balance uh changes um and we also like help you manage addresses and we have like a type system for addresses whether they're like EAS or contracts so it can help you catch issues um if you're if you're accidentally your governance proposal
accidentally talks to the wrong contract okay so the first the first thing to cover is the um addresses contract so this is just a place to really really easily store um all of the addresses associated with your project um and then do type checking on them so uh before you run a governance proposal or before you do your deployment script um you'll create a new instance of this address object and then it will read in Json files in your repository um and and store uh these addresses uh and then it also does type checking so if you say like oh this address on mainnet is a contract and this is its name uh if you
load that contract up and it is in fact uh not a contract uh it will it'll fail loudly and it'll tell you like hey there's something there's something going wrong here and in the future we want to be able to support um we want to be able to actually like support like bite code checking so you could say like oh I expect this contract at this address to have like this bite code and then if it doesn't you know you say okay there's something wrong throw an error here um and so we can see on the right here we have um what this Json structure looks like so we just have some token addresses um and then you know then if you're like changing the addresses around it doesn't need to like recompile
your smart contracts and then you know there's some more getter methods like you can say hey is this an address a contract um is this address on this chain a contract um and is this address like set so do we actually have this Alias uh is it is it used or not okay and then we have a deployment script here so um we're going to just go ahead and um we're going to say okay hey um have we already do we already have this uh Bravo Vault uh set in our addresses object uh if not we're going to go ahead and deploy a new one and we're going to go ahead and transfer
ownership to um our protocol time lock and then we have the same uh check for the The Vault token we say okay hey is it already deployed um if it's not deployed we go ahead and deploy it um and this allows us to really easily like simulate let's say we have a governance proposal that needs to add a new contract to the system this means that we don't need to like you know in our test file we we have like we we parameterize and deploy this contract um and then oh but then we have a different way that we actually deployed in the real deploy script like we actually just get to combine um our deployment script and our governance proposal uh into one thing and our tests can go ahead and
leverage that and so this is the uh build stage so this is this is this is some really cool stuff so normally if you're writing a governance proposal you know You' have to like specify it in Json and You' say okay this is the target uh this is the call data and then this is the value right and now you read that in and then it gets you know turned into um whatever format that uh your Governor uh expects so maybe it's like a multisig maybe it's a time lock maybe it's a like Governor Bravo um but here what we can do is we can actually write this governance proposal in plain solidity and uh the first step we're just you know loading some addresses up
so we can see like we use these keys and the keys will tell us like will give us the the addresses back um and then um then we start making the calls so we say okay um we need to um Whit list the token number one we need to approve it and then we need to deposit it to prevent maybe like a share price attack um and then what that does is under the hood with uh Foundry cheat codes it records all mutative calls um okay and uh all those calls then get translated into the governance type that that you're working with um and this is completely modular
so whether you use a multisig a time lock Governor Bravo or even your own completely bespoke um system all these components are really modular you could just pull them off the shelf and use them to um build whatever kind of um system you want and um yeah so we have support for nois safes um out of the box we have support for open Zeppelin time lock controllers so that's like very nice to be able to just kind of kind of like pull those off the shelf um we also allow you to generate uh call data so we can have we can have multiple um developers we can all be running uh these scripts
locally um and generating this call data and then comparing them when they go on chain and the other really cool part is uh you can actually track proposals so if you send a proposal to the Dow uh you know and let's say your computer's been compromised and you send call data on chain um that's not what you expect because your computer's you know compromised then what what what can happen is uh your integration test Suite can track the proposals that are on Chain versus what you have uh locally in your repository and it'll say oh wait a second um there were supposed to be three calls and they were calling the The Vault the token and then the Vault again but what's on chain is actually
you know calling some other addresses so we don't actually know what's going on here um so that can help you um um catch catch those kind of issues and governance attacks okay and then finally we have the validate function so this is part of the standard um Forge proposal simulator just interface so you can fill this out and it works for both governance proposals and your your deployment scripts you just say hey here's you know these two contracts the token and the Vault uh and maybe also the time lock that were um that were like that we touched in this proposal and then say Okay um did this token actually get Whit
listed um so we do like validations and make sure that the state uh is is correct oh did the balance of the Vault change oh is the total supply of the token what we expect is the token owner correct is the owner of the Vault correct um and this allows us to validate both post- deployment script and post governance proposal execution um and see that everything um looks exactly like we want it to okay so now we're going to go to an example application if you want to follow along locally um I'd encourage you to scan the QR code or if you don't want to scan the QR code you can just enter in the uh URL um I'll give everyone just a minute to get that
pulled up and so um what we're going to do is there will be uh we'll do a little code walk through here we'll go through uh an example application and we're going to go and try and find and fix bugs um using this tool and um so we'll go ahead and start on um Vault 0000 so basically um you've been asked to build a I guess this is kind of the the specification of the system you're building a vault contract that allows users to deposit tokens uh of the same value and then they can uh withdraw those tokens at a later date um and so an example could be like you you would
Whit list or you'd have a vault that's for um we uh we eight and we n right just two versions of wrapped ether let's say and so then um we would go ahead and create a vault with those two tokens um go ahead here okay so um I guess we can start on the interface for the vault so we have a deposit function and we have a it's a little smaller we can make it bigger so
we have a deposit function we have a uh withdraw function um you can specify a token we have a list of authorized tokens here um and so you just pass in a token address and tells you whether or not the the token is is uh whitelisted um we then have um we have the first governance proposal SL deployment script here um and so we can you know we have to do a little bit of setup here we have a description we have some other you know setup items and then we have our deployment
script here which goes ahead and you know checks hey have we gone in you know have we created this new Vault with these tokens um and then we have the validate function we're saying hey you know was usdc die and usdt are they all um deposited or are they all like authorized tokens within this fault um so I'm going to give everyone just a minute or two to I guess think this through look at the code see if they can find uh any issues with it um and
um yeah and then I'll I'll take questions or answers from the audience so here in the Constructor we go ahead and we set our authorized tokens we have have a deposit function where you can go ahead and deposit your tokens um and make sure that you know the token is authorized when you deposit it um and then we we we increment your balance we increment the total supplied amount um and then we we transfer the token from the sender into this Vault contract and we emit a deposited event and then the withdrawal function
um we have a you know pass a token an amount um we do a we have an implicit check here on the withdrawal um and then we also have um integration tests here so this integration test you know we have all the different tokens that are deposited into this Vault um we set some environment variables and we go ahead and run the the the proposal we and we deploy the contracts and then we just go ahead and run the validate function so we make sure that hey you know does does it all check out does it do what we expect it to do um
and then we have some integration tests here where we're actually running against uh a mainnet and saying okay um you know is our can can we can a user deposit die can a use it deposit usdc um and can they can they deposit uh us C uh and then okay well now that they've deposited can they withdraw um and then now we have another use case where oh we have someone deposits usdc and someone deposits usdt and then um then each user decides that they want to withdraw a different token than they deposited and so you know making sure that those State transitions um also work and then we have a helper
function uh down here so has anyone been able to spot the the bug okay all good um it is a it is a subtle one so um the bug in this system is so the Vault actually the Vault actually works fine um for light kind tokens um but it makes a makes an assumption and that assumption is that all Vault tokens um have the same denomination the same decimals it doesn't do any decimal normalization um so we have all these
integration tests here but unfortunately uh they didn't test uh the one the one case that would have uh that would have uh shown the bug which is that if you deposit one die you could just steal all the usdc um because it' be very unlikely that there would be you know trillions or you know some huge number of of usdc in the contract and so if we look at the uh deployment uh script um we have you know our tokens here and and this was the bug was in our deployment script like we incorrectly parameterized uh this system okay
just wait for this to okay so um yeah all the all the invariants that we would expect uh in this system um based on based on the Vault and the total Supply you know all that works but again we have a bad um we have a bad deployment script so okay we're going to go on to the next exercise now okay so this um this next Vault um
we're going to just like make things uh simpler here so we have like the same uh data structure so this is all you know we have an author we have a list of authorized tokens we have uh user balances and then we have the total amount supplied um you know across all the different tokens and we expect the the same you know invariance to hold from the previous fault which is that the total supplied is going to be equal to the sum of the the balance of all users and that the sum of you know the balance of the Vault of of all authorized tokens should be greater than or equal to the total supplied amount
um that's pretty pretty simple and um now instead of treating all tokens uh and like not worrying about decimal normalization we've added a decimal normalization function and so so here we deposit um we make sure hey the token is authorized we pass in the amount we then get the normalized amount based on the uh the amount passed in we increase the user balance by the normalized amount and we increase the total supplied by the normalized amount and then we go ahead and transfer the tokens in you know nothing really changed there um we added an additional check which in the the first version of
The Vault um 0000 we were able to withdraw an unauthorized token um and so while that wouldn't break the invariant it would have been like undefined Behavior or something we weren't expecting so we're just going to go ahead and add that add that in for just good measure and so um yeah we have our withdraw function here and now we have our um get normalized amount function so basically um if the amount is uh already has 18 decimals we don't need to do anything um and then if the decimals are under 18 then um
um you know then we need to normalize that up to 18 so that uh things just work and we're going to say hey just like for for the sake of um you know for the for the sake of this exercise we're going to say that like if you have more than 18 decimals like that's not standard we're not going to support that um but that is you know that could be something that does happen Okay so now we're going to go ahead and take a look at our uh deployment script so we allow usdc and usdt I don't think we need to you know use die like that's that's fine we can just uh simplify things here um and then we have our validate
function and then we can go down to our tests and so we just have usdc and usdt and you know we go ahead and we have a um we test depositing we test multiple users depositing we test users withdrawing depositing and then withdrawing uh you know we we test uh two users are swapping so one deposits usdt one deposits usdc and then they both withdraw the um asset that they didn't uh deposit um and yeah we still have this helper function so that'll just that'll just help us out here um but there is I think there is a
problem here here I think there's something I think there's something wrong somewhere here and if anyone has any ideas let me know okay so the issue that we have here um is is is of course the issue that we didn't uh test for so if we take a look at the um if we take a look at our deployment script here we removed die and because we removed die um if we would have run if we would have run the validate
function we would have gotten an error that said hey you know die should be authorized um but we forgot to run that in our uh in our integration test suite and so we we didn't catch that there was like some discrepancy here between oh did we want to include it or did we not and because we forgot that um because we forgot to include D um in our our test Suite then it meant that we didn't test any token that had 18 decimals because usdc has six and USD usdt has eight and we didn't test one with uh 18 but if we look at the um Vault uh one implementation um we can see here that
uh if the decimals are are 18 uh there's there's nothing here that will that will handle that so we would have a pretty big problem and so that would mean if you deposited any amount of a token that had 18 decimals um you would get nothing uh and it would and this contract would then have your funds which would not be not be good um so basically um because we didn't uh because we didn't have a test here uh and we forgot that in the deployment script we you know we missed out on like a pretty easy bug that we like we really could have found um had we been looking for it okay so now let's move on to
um the the next version of The Vault so we have some new requirements here um we need a way for the owner to add new tokens on the Fly um and the business team said that they wanted a way to um remove tokens as well but you said hey look sorry we um I can make this bigger if you want to read it um but if you said hey look if we if we allowed you to remove tokens then uh then you know then you wouldn't be able to withdraw because anyway so it would it would increase the complexity you'd have to have you'd have all these different edge cases and they say okay that's fine um but they just want to be able on a way to add uh
tokens uh on the Fly and uh we so we went ahead head and we added um just a single function here uh the add token function and then um we went ahead and and fixed the bug with the normalization so the normalized amount starts off as the amount and then if the decimals are under 18 uh we go ahead and handle that now of course we're assuming here that you're not going to have any like 19 decimal plus tokens which I think is like a pretty safe assumption uh for most defire protocols um and there's actually uh there's there's no bugs here um and so then let's go on to the next um
contract so now we need to make the contract um upgradeable we need to preserve all the existing functionality um and we're going to we're not doing a forc you know upgrade because the previous contract uh it wasn't even upgradable so we couldn't we couldn't Force the users into this upgrade if we wanted to and so we would say Okay users you know you have to migrate into this by optin so you have to remove your liquidity from the old contract and deposit it into the new one and we're going to zoom out okay so we have this contract here oh this is the this is the deployment script so we can just go over that now so if the Vault implementation isn't
deployed we go ahead and deploy it we add it as an address uh we whitelist all three of these tokens usdt die and USD our owner uh is going to be the our our time lock contract um then we're going to go ahead and we're going to build the uh initialization call data for um for the proxy and I guess the proxy admin now is created when you create the proxy so uh we don't even need to worry about creating the proxy admin but the proxy admin owner is set to the owner that you pass into the transparent upgradeable proxy so you just have to keep that in
mind sorry um so we go ahead and add the address we fetch the proxy admin from the um from the proxy and then we go ahead and add that to our our address's um contract now we have our validate function here so what this does is it makes sure that do usdt and USD uh C are all authorized tokens um it also makes sure that um you know the the Vault the proxy admin is um the proxy admin owner is the compound you know time lock um contract
and so that's the high level of our deployment script and then we can take a look at the Vault contract itself so this contract is going to be it has its storage um in another contract so that'll just go ahead and manage everything and keep um keep the code clean for us and um yeah then we have our events here we pull our libraries in disable the initializers and the construction CT so you can only you know talk to the proxy contract you have our initialized function our initialized modifier we've added some events to just kind of make
things uh easier more um just give us some visibility into State changes when we initialize the contract we've added a add token uh function and a set max Supply function so we've also added a new introduced a new variable into the mix which is the max Supply so users can only Supply up to the specified um maximum Supply amount um and and only the owner can call this now our logic here um for the deposit it's unchanged except we added this one new require and we just say hey make sure that the total amount that you
supplied plus the normalized amount um make sure that's not um going uh above your your your supply cap and everything else is is pretty much uh the same here um it's the same contract it's the same system and you know our our normalized function is fine um everything looks you know pretty good and there's not any any bugs here as as far as I can tell um okay so now some some new requirements have gone ahead and come in again so if we go to the exercise 4 the
the final exercise um we need to actually be able to make the contract possible and but we also want to preserve all the previous functionality um you shouldn't be able to deposit when the contract is paused um and but you users should be able to withdraw their liquidity uh even if the contract is is paused and only the owner can pause and unpause um and then once we finish this implementation we need to actually go ahead and upgrade um uh this is going to be like a forced migration where users uh of the old contract are now going to be forced to use uh this new contract and if they don't agree with it like that's fine um they can go
ahead and and withdraw uh before the upgrade lands so we can first start start by taking a look at the deployment script um so we're going to go ahead we set things up we have our description here um the deployment is pretty simple because it assumes that we've already ran um the the third deployment uh script which deploys the proxy admin um the proxy itself and you know make sure that's all set up just right um and then yeah if if this new V4 contract has not been um deployed then
uh we're going to go ahead and deploy that here and we'll add it to the addresses object um and now we're getting into the meat of the governance proposal here so you know we load up our different um different contract addresses here um and these are all static calls or calls to the addresses object so they're going to get filtered out by the forge proposal simulator framework and um then we go ahead and call the proxy admin and we upgrade the uh Vault proxy contract to the V4 Vault implementation and then we also need to set the max Supply to you know some new
number so it's going to be a million so that'll be like the supply cap uh in terms of this fault so maybe it's a guarded launch and we're only gonna allow so many so many users to deposit um and then we have our you know validate function here so we're going to say okay hey are our tokens are they in the authorized list um is our Max Supply is that set correctly um is our owner still the time lock because it it shouldn't have changed right that's that should be should just remain static um and so now we can go over uh here and so here we have um a new storage um layout so that's the uh Vault
Storage posible contract so that just extends The Vault Storage ownable and just um basically just adds the new posible contract at the end and then we can go through this contract so we still have the initialized function nothing has changed there the Constructor everything's you know that's the same um our ad token function yeah we still have that our setmax supply that's that's um still in place um and then we have our our pause and unpause functions so only the owner uh can call these and um yeah it's it's
pretty it is uh yeah that's pretty simple our deposit function function um yeah you can only call it when it's not paused so again that's like a very very small change um and then we have our withdraw function there's no you know pause modifier on it you can always withdraw so but I think there is there is an issue here and we're going to we're going to we're going to dig in so um we already have the deployment script we have um this build function so here it's going to you know this framework for proposal simulator it's going to pull out all of this call data and package it up to talk to the uh Governor Bravo um and so that happens like all
under the hood it extracts these calls and turns it into a format that uh this Dow contract can understand and then we're going to go to this um test Vault um4 contract and this is going to you know we have a setup function here where we deploy the um the uh 03 so that we deployed the um the old contract versions um and we set up the proposal we deploy it we set the addresses in uh this contract to be the addresses that we already deployed so we just like share a reference to that that same addresses object so we have all those addresses that have already been
uh deployed here you know we set uh our our token our stable coins and we set our uh Vault contract um I guess we go ahead and bump up the max Supply uh as the owner because why not um we set up the proposal we deploy the uh the contracts that are that are here so we just go ahead and deploy the V4 Vault implementation if that's not already deployed and then we're going to go ahead and you know just we have like one test here so we have to kind of figure out like what what is the test that we we should write that will that will catch the bug um but you can see there's there's
nothing um and yeah there's there's there's some things that are uh we don't have so we're we don't really check any state of the contract like what was this contract State uh before we executed this and then um what was it afterwards and so um basically because we don't have any tests here we we we don't really know uh what this governance proposal did um and I think there is okay it looks like some code got
deleted that would make it easier to test this um but uh basically there there's the the bug in this contract is actually it has to do with the storage slots so if you had deposited your uh tokens into the um V3 of this Vault um into the Vault Storage ownable and then uh you deposited and then the V4 upgrade happened um you got Force migrated over um and so we have the ownable we have the supply but then the authorization and balances mappings got flipped in storage and how they were inherited so the solidity compiler just says like oh wait a second the the
storage um the offsets are now different and so that's actually um in in this the fourth um uh deployment script we because we don't have anywhere in the tests where we run this validate function um like a simple like if we literally just said um if we just did that that would give us a failing integration test because it would say wait a second uh you've built this proposal and then you ran it and then for some reason all of these tokens are no longer authorized um what what's going on there and so basically this would allow you to to really quickly and uh easily um catch catch bugs like that
because hey all of your all of the state of your system is just just really easy easily available to you um and you can leverage your entire integration test Suite um to catch these bugs um and so maybe you don't even need to like write new tests because you just say oh can a user deposit into this Vault that I expect is authorized and then oh for some reason you can't um and all of a sudden you're getting a revert that the Vault isn't authorized and so you say oh wait a second there's a there's an issue with um the storage offsets okay so yes so V4 the the exercise four
um we had an issue in the storage s offsets um so what did what did we learn from all this so um you really have to use all of the the test methodologies that are available um starting from the bottom of the stack and then uh working your way up so you start with the cheapest you start with your unit tests you start with your integration tests and then you go to more expensive methodologies um over time and you you will you'll always have blind spots you know no matter how much uh you try to think about all the different edge cases of the system and all the different Corner cases um inevitably there will be uh bugs or there will be there will be
things that you don't foresee and so that's where um you know using a lot of different testing methodologies and a lot of different tools will help you find these these harder to catch bugs and getting Auditors and and The Works involved um you should you should be a aim to be as rigorous as possible you know think through all the educ cases think about your program as a finite State machine um what are the possible States it could be in um do we have relationships between variables or invariance that we think should always be true um if so how do we express that in um in a testing framework um can we yeah can we write invariant tests can we
formally prove it can we use um yeah how how can we prove this to ourselves that this that this thing is true um and then okay you say okay we have these relationships between variables but also you need to verify your state transitions right um and make sure that okay certain program states are unreachable or certain you know State transitions uh can't happen um and you know I think that there's there's really like as the industry has like progressed we we've invested a lot more in fuzzing and in formal methods and in in like test methodologies that really are good at um discovering logic
errors in in code and I think that as we've done that and as we've gone you know gotten better and better there um like our Focus as an industry has like gone away from um these other kinds of bugs which is why I think it's really important to you know also test your governance proposals and deployment scripts and um like really get a lot of eyes there because um where attention kind of goes that's where bugs disappear and when you when you have all your attention in one place then you have these other spots that okay hey things kind of slip through the cracks and then I think one one final call out is that you know a lot of a lot of time should be spent on
um uh on like I think the majority of of time should be spent on on testing and should be proving to yourself that you know this system really does what I think it does um because uh if you're spending all of your time actually writing smart contracts then you're going to get to the endend and you're going to have a really buggy system and there's going to be just a lot of things that you you've missed and so I think it's just really important to like be cognizant of where you're spending your time as a developer and make sure that you know you spend a lot of time um testing and hopefully a majority of your time um because I think that's really the hard part is is proving to yourself that okay yes uh
this code that I have written is correct and I'm like sure you know beyond a shadow of a doubt that like it does what I think it does and there's no weird uh weird cases or Corner cases or if there are weird edge cases I understand them um and so I think like a good test of that is like if you show up to an audit and you have um a you know a full specification sheet or a full sheet of all the edge cases that you already expect and know about your system and so then that way um you know it it it'll be easier for uh for your Auditors to like actually go and find the higher impact uh bugs okay so if you want to um use the
forge proposal simulator um you can scan this QR code or you can go to one of those these two links so if you go to docs. solidity labs. IO um you can go ahead and uh yeah you can go and check out all the documentation we have on things um oh and one more thing um there is a uh State diffing feature uh in in the tool so if we can if you can see here so in the um in the fourth proposal we go ahead and we upgrade uh the contract and then we uh we set the max Supply variable from zero to I think
it was a million uh or scale to 18 decimals and so if you look at the uh proposal changes uh the Vault proxy contract had two changes so the first one is it um it changed uh its implementation address so it changed from the V3 implementation to the V4 implementation and then the second one was the um slot I think the zero slot which was which would be the um the maximum Supply and so they you can see that it started off as zero and then it got updated um to a million um and that was you can do that all from the command line you just specify um a few Flags here so you say
okay uh run the proposal print out the call data um and you know we don't even need to run the validations here just just print out the call data and show me the state diff of what I actually um did yep and you can uh feel free to uh stay in touch um I'm on Twitter at Elliot ZX um my email is Elliot solidity laabs doio um and we are hiring smart contract Engineers so um please get in touch thank you so much [Applause] okay there won't be questions and
answers e e
hear me okay um Saud cap everyone I'm jatas I'm really happy to make this presentation to you and share a bit a bit about my process how to leverage your knowledge and how to Transit between blockchain stacks and I'm start uh talking about me so I've graduated in computer science I've worked five years as web and mobile bi developer um during these years I worked with PHP reactive react native and a lot of a lot of stuff um right now
I'm two years uh working at spear beit as associate Security researcher and one important migration between my career was um I was working as react native developer and then appear opportunity to me to start working as flutter developer and then I have only one month to change between stacks and this like all of this experience brings me here to show you more about how can I I use this process to learn new
languag um so my proposal here is to get you a starting point to migrate your knowledge in solidity and start uh learning R and also um do it fast like not um watching tons of videos and like worth um lost too much time to make these kind of migrations um the agenda today I separated in two main steps so the first one is the developer mind set so we are going to check the difference between
the blockchain stacks and understanding the code then researching the firw workk and then we I will bring you a code here that we can read and understand the most of logic of it and the next step will be the hacking mindset so that you can use that what you already learned in solidity and bring it to the Solen blockchain and the last one is the conclusion um so already starting the the difference between like all everything that you can see here I
didn't get it at the first moment that I start learning Solana so it you happen like in a SLE so so you can get the basic stuffs and while you get deeper in the in the code you can learn more but just to bring you some basic stuff like in etherium you have one if is they have 18 decimals and his way is one way is the the last amount in salana we have the soul and they call it Lum ports and have only nine decimals uh in eum usually you have only in the single codes everything together like the logic and the data where you
can start everything in Solana we have two different types so you have a logic program and a data cont then in transaction ethereum you can only call a single function like when you send a transaction in Solana you can call multiple functions in the same transaction use different signers so we have multiple signers as well and in etherum we have the pr compiled contracts in Solana we call it Solana program library and it have the demand basically contracts that you can interact like to create to and some kind of this stuff and in narum you have the
self-destruct right now it changed a bit but in Solana you can also close and delete the account so you have to close close it properly and to not have any kind of issue and another interesting stuff is that in ethereum you have the create to that you can derive the account from it you can predict the address of it and in Solana we have the PDA which is the program sorry let me close this okay so we have the program D derived address which is the PDA so usually you when you want to create some
data account from a program you use this kind of structure so uh starting already with the coding language so in this step you don't want to uh have a deeper understand of how the how the the rust program language works you just want to have like an overview of it so you don't don't need to understand everything that pursue you can understand and the step by
step and we are going to do it by um having it in parallel of how eum works so in etherum we have the Primitive types that is the uint int address Boolean and bytes this stuff then we have the how to declare this variable so we use this primitive type and then the name of the of the variable then we have this array type how use probably you all know this but it's how how can you do it's compare
everything then we have the the array then we have the mapping that you can map an address to a integer like checking the balance and you that you a user could have so we have this declaration then we have the structure type where you can have like a person car or anything and you'll have like the name in this example we have the name and then the age so a person you can declare a person like this way we put the person p and then the name the age and if you want to
change you can directly change the name just adding this and we also have the Nome which is just to add like a type to something and bring it to rest we have similar things so we also we were going to have the Primitive types so we have U represents the U in and it goes to eight to one 128 then we have the integer the Boolean bytes it's kind of similar and how to
declare a variable so you use the keyword L and then put the name then next is the type and the amount and the the value that you want um so if you want to declare an array you need to use the L and the motk word in this case is us it uh to let the variable be uh changed so in this case if I want to add values to this B variable I will need to use the mute keyword then I can access any value and and uh index in the array and can
change it without this moot k word if you try to change the variable you're going to get an error from it do we also have the structure types so in this case the user you have like the Boolean active and the user name and this case is quite similar to solidity but the type is after after when decare the the variable name also we can declare the user like this you have the moood keyword again and you set it and if you when to change uh the username will just um add
like this string from and change it we also have the act the enome it's pretty similar to and like you can add this deposit withdrawal types so right now we we just have like an overview of how R works and you can already start uh read some code but first we need to learn how to declare and also use functions so again comparing the ethereum and Solana
solidity and R we have like to decare a function we have the keyword function then the name of it we declare the input type so we have u in 256 A and B then we have the visibility of the function and if you want to return anything you add the keyword returns and the type of returns the type of it and to return we also have the the keyword return and return the values right so to use this function we can declare these two variables A and B and to use it to just call the function
and pass the inputs now take a look in the rusty uh we also have the visibility first so it's a public function then we have the keyword FN which means function the function in solidity then we have the name of this function we have also the input type so A and B but it's quite similar we add the the type before of the name of this function and to use it you declare these two functions and just use normally like
solidity so there isn't too much difference to get the basic knowledge of versy from now on you can already Identify some part of logic of the code and then there are also some different syntax from uh solidity here we have and the four and Y Loops so in Rusty we can declare the four using this syntax so we put the four and then the the name of this variable and the range
of it and then you you look through this code and the while is also quite similar so you can you can see that you can just read everything normal and veryy understand it the code okay and we have the also eil state statement and the match so the ifls we don't use the the braet you we use the if keyword and then the corporation the the statement inside to check if
it's equal to something and then El if else it's pretty straight forward everything here then we have the match the match is similar to the um switch case where you can see in some in some cases so to match the number if it's equal to one you have this Sprint if it's equals to two we have the another one and in case of theault we have the another print this and this and now like you we have
um a overview of the code we can already start jumping to the framework we don't need to spend too much time um studying a complex stuff and now how to work and spend really much time understand the language watching videos and all of this stuff and we can check um how the architecture of a program works so we have The Foundry in Foundry everything is can be found in the in this three uh folders so we have the script to run the tests and the source in the source we will have uh the main
logic of this of the code right so you can check here that we can declare a contract uh counter which is the most basic contract here so we have the number and then this number we can just increment it and we can also set it or anything else you can do in this code we will do inside this contract um the counter contract right and okay and now we can check how the
anchor framework works so there is like a lot of files here it seems like a mess at the first look and looks like pretty complex if you don't understand anything but if you can check this folder here we can see that our program is defined inside it so similar to the Contour we will have a s Source folder we have the program then we have the name of our program which is counter and inside it we have the source folder and inside the source folder have the lib file so the entry point of it it's the the li. RS
file then we have a bunch of code here also you don't need to worry that you don't understand everything because at the first time as I said we don't need to understand it we just need to understand the logic about it but to get a better the upper the this rectangle have the declare ID in salana is a little different because we Define uh the public address before we create create the program so we add the this value
here then we have the the program macro and a macro in Rust is uh some it's like a function that we run background and make something something easy to you so you don't declare everything from the beginning right so we have our program counter here in Solana we also as I said we have the program and the data account so we have to initialize this data account before using so usually when you start looking at the code you will see an initialized function in this
case uh we have the initialized counter function and we also have the increment function here as you can see the inputs here that's a lot of weird stuff but we are going to check in a while everything and we also have the the inputs declared here which is like the initialized counter the this they have like a payer and the counter so we are start starting a data count called counter and to use use it you uh have the struct called
increment both right so the idea until here is to understand how where we can find uh the files in the framework because usually when we open um a a project we that like in a language that we don't know we don't have any idea where to start and begin reading the code and check the entry points all this stuff right let
me so um we have uh we have overview of the project Pro architecture and how to read some small pieces of code independently and right now my idea here in my process before I understand the codes and the file architecture is to already start reading a code like get divid because when you read too much um tutorials you can spend too much time uh reading it and when you go to a real case uh the file architectur is completely different from what you say
what you see in these tutorials right so let me where is my mouse okay right so I got uh I think you can see better now so I I got this code from a competition a grass competition they have uh three programs but I think we can have time to understand probably two of it or one I'm
not sure but uh we have the road is taking and the token are dropping so if you have an idea how a token a drop Works in etherum usually you have an Merle tree where you add all the user address and the amount of each user you receive from it so the user uh when call it will prove that he belongs to that tree and will receive the rewards and there and then uh they have a structure to mark that user already received this reward right and similar here we are going to
check it right now so in this one you can say that it has the program folder let me close this first so you have the program script test also really similar to the etherum then we have the programs here inside it we have our program the token IR drop and the folder source so the first file that we need to check here is the lib which contains the all logic from it so usually I reduce everything here
because there is too much information when you start and we don't want to get everything first look so um here this this macro here is like to have the input type of the function so we have this transfer CPI type which is a structure that we can record here the structure type then we have like a bunch of macros as the account here but we can focus only on
the on the variables name here and the type of it similar what we look at the the first slides so we have the recipient payer and the system program which one like when I have DED about what this means and I don't understand it I usually get back and search on the Google about it so like if I want to understand what is the signer you can go like to documentation on some video that could explain something and get back like moving from searching and to
already reading the code right so our main code here is declared inside the token R drop module then also we are going to have here the initialize function will which will initialize the Merle Tre similarly which we have on ethereum then we have the claim function the set admin for these initialized data function and lock CLS in case you want to and not enable to anyone Clan the clan the air drop right so to
understand a little bit more about the ACT architecture we are going to have the in the instructions folder which is the entry point of each function so when you saw this the folder named distruption we we have like each functionality separated by another file right and then we usually have the state folder which contains the type of the data account that we want to restore so we will have in this case I'm going start from here we are going to
initialize a Merle a new Merle distributor so we have this function handle new distributor to this function I will have a this file new distributor and we have the data structure of this distributor here in I state so in Solana we have for almost all the project that use anchor this type of structure then we can see this function we open the new distributor we will find it here right so again take a look uh we have a bunch
of uh declarations here so the struct initialized struct then we have the new distributor struct we have a bunch of macros but again we don't need to understand it there these are like helpers which will be checking some logic and will help you like I don't need to to check if the owner I have a macro that help me to check this and again while you are getting deeper in the code you are understand it more but the idea here is to understand the logic of each function and probably
we may find some bug here so to to add a new distributor we are going to put the the version and The Hoot this is the Marco hoot three of this as you can see here above we are getting the distributor data account here we are setting uh some variables to to it so we have the mot keyword if we didn't have this keyword probably the code will not work so we are the div version The Hoot the minting the token
we are like setting everything related to this this distributor right and then we emit an event and finish so this is initializing a new distributor after that we have set the data of the distributor and any user can call this data and Clan the tokens right so now we have the Clank function here so the user need to pass the proof and the amount of tokens that he will get here the allocation again we have the handle new
clim and where you can find the logic the logic of it it's in the instructions So the instructions here you have the new claim right and you can jump directly to the logic of this function which starts um here handle new Clan uh to like at this point we can have an idea how to read the code but we can also give one a step further to it so we can check like
how how this new CLA struct is declared so we have the the distributor account which is the merco distributor type then we have the claim status if this account is already claimed from and then to uh who is claiming then the token program because uh Solana is different from etherian so we need to call a a a program to transfer the tokens and then usually you have the the system program from
here so again the user pass the proof the amount of allocation and you can load the distributor which we we just uh created then the account which you Clan then it's this will verify the Merk proof you can also use like the comments to help you understand something that don't make sense to you and then we get the hash of the Merle tree and we'll check if uh the proof is added to the root of the Merkel
tree then we have the the status of it there is one interesting thing because um we can't Story the data in the program right so we have the the air drop program here we have the merco tree data and we can't store the data of each user direct here so you create another data extruder uh which will contains if the user already claimed or not his so you add the the user info here the climent and the amount of tokens that he
allocate is allocated to here and then we have like this complex code here we also don't need to understand but it's like a token transfer at this point we just want to know that it's a transfer tokens from probably the the program to the user right and then emit an event from it so we can also set the admin of the the merco distributor and we can
also lock lock clim to this so like check first the lock CLS so we'll have this function so right here we call the handle lock function then we can check here the client uh handle lock claims right function sorry then it load again the distributor and in the distributor you have the lock clients variable and it will set to aoan that the user pass here right so it's um the most easiest code that we
could have in Solana and it's not too much complex so yeah an user can clan uh the admin can lock it and you can also change the admin here to another admin and while while we are get into so the code we can check like which is the signer of this account and here we can check like if the the admin the P admin is need to be different here in this case to set the
admin and then we the admin could call this function right so in this code we have uh logic key issue uh if anyone can could find it while you go just checking the logic please um get up your hand no it's like uh the logic key here is you create the miracle tree you add the hood to it you can claim it you can lock it but if you can check when you Clan it there isn't any checks here to check
if this distributor is already closed so my idea here is that you can start already start reading reading the code you don't need to care about like what macro what is this context type and new clim type you can you can take a look like in this new Clan you have a bunch of variables but if you can simplify you could like remove this remove this remove this remove
this remove this this one remove like every comment to make it simple then we have a structure type here the structure is the new claim and you have these variables inside it distributor claim Stratus from to The Climate token and System Program so you have an idea of how is the structure of this new clang and then have this in mind you will see like you're getting the distributor here the clment which is already defined then
some logic to verify again the M roou the status if already claim all so you can already know the logic behind it I forgot to pass about this state but this state is here here we can declare the data structure so the the new Marco distribute will have uh this information inside it the data the data count of it and we could have also some implementations related to it like if we want we could add the logic here to
verify the hash of it and instead of declaring it here okay right and I don't think we are going to have much time to like dive deep into the rot roin stake but similarly we can have this like this is a bit different from the other one so so let me close everything here so we have the program the token
staken here the source folder inside it then we don't have the estate but they declared here so here we we will find um everything related to the the pool so this is a staking program so similar similarly in ethereum we have the staking contract where the user put money on it and can withdraw money from it so we have the same same thing here which called the reward pool so we have like these variables declared inside it and some implementation as I said here when you create a new
one then you can calculate the uh rewards of this then we have the the stti pool which is also have something some variables inside of it and like I just got this code where I start looking at it going to the lib lib file so the lib we have here the program name and again in each alizing they taking pool you can transfer authorities like transferring their own adding a reward to that pool uh you can
deposit uh claim everything withraw from it in this one uh we have this lashing function so the user will St and in case uh it will kind of give him the voting power to an operator and in case an operator done something bad then it will slashing this and like for each function we have it separated here as well uh we can like checking probably the deposit function which is the the easiest one so we have the structure of the deposit again with some variables we can
uh try to draw some G diagram of it adding every variables and have every in mind but the main function here is the deposit handle right you can find it here so as you can see this look looks like pretty complex at the first time you look but if you try to read each line and understand it every time you're going to understand all the code right so the user here to depos he will add the
amount and the lock up duration like I want to lock up my deposit for one week for one day for any time so uh it will so you pass the pool that you want to deposit right and then it will load this pool check the minimum time of this pool and check if you're your time that you inut is enough to add it so it's it's it's really different from from ethereum so we have the pool here but when the user deposit you don't start the data in directly in the pool like
for each user deposit we going to have a different data set for this deposit that's why because we create a you H stake depos receipt from it and then we add the the owner of it the pool of the user is depositing the payer the amount of that user deposit the effect effective stake it's calculated here in this account in this function then we have the lockup duration and the current time of this deposit right so I hope you guys understand like how
to uh take a look at the logic key although we don't have like any idea of how those things really works just looking at it you can start checking each line of this function and as example I'm not sure um and like what what these things mean like get effective you can look at the code if you find this function in another place to understand it or if you don't have it it here probably it's something already predefined by the
solam program and then you can just give a time from this code get back to Google search a little about how these things works and then get back to it and this is usually my process of how to get a new understanding of new code like usually I don't spend uh too much time uh getting into tutorials because what I've already noticed from all my experience is after you watching like 30 hours of video explain some new language when you go to some competition or trying to understand some new pattern
you you will not remember everything that you you have watched so the idea is to get everything into practice like and get back learn and then practice reading the code get back learn and do this Lo until you can figure out how everything works and with some time you will get um better right so for this we uh look at uh real project architecture know where is the entry point is located and try to understand a bit of the logic of each entry
point and now with this we finish the the developer mindset I do this Loop until I can't understanding all the code behind it so like in this presentation I can't dive deep more into too much details here because we are proba spent some days trying to understand everything like I've I spent um one or two weeks learning Solana and understand the code while I've participating in the grass competition and I could find a medium issue
um which uh nobody found it um then now we have an idea of how to read how to get everything and we could start developing our mind our hacking mindset so again I have an idea how ethereum works like I know how the control access Works in etherium so the owner just can cause some functionalities we have the same thing here in Solana if you take a better look at the macros you can see that there is an access control to it if you don't have it probably you can break some of
this functionality we also have arbitrary calls so when you passing an account which you didn't verify it properly you can make and any call and calls to another data account and break it and in Rust we also have underflow and overflow so in most of the codes we are con converting all the values and checking if we don't have any kind of this issue and then we have also the uh the project vulnerabilities like in landing project
usually you have a bad liquidation issue and these kind of logic issues we can also find in Solen program so you can reuse everything that you can that you already know and try to find some vulnerabilities in this code so we have like the landing staking program similarly so we going to have an incorrect re calculations and incorrect uh liquidation bad liquidation and all of these logic issues I put these in Project vulnerabilities and then we also have
some uh Sol common vulnerabilities you can easy check like uh R common vulnerabilities you have a list of it so Sol common vulnerab ities ethereum common vulnerabilities and you can similarly take a look at these things so in Solana we have like we can close an account if you don't close it properly you can revie this account example the user um called the uh the the claim in the the Marco distributor so you add the value to it you could also so just close this data
and like to not let the user re open but he could um if you don't close it properly the us could reopen and can again some tokens uh we have the account matching then um when we we are defining the the stretch you have the type of this account you could don't have this type so you can add any type of account to it and read instead of you reading the owner you are reading some handon value from it and we have the type crossplay and reinitialization attack so um if you
search for it we will find like 10 Common vulnerabilities that you can already start founding it in Solana projects and um so after that we know that we could um have the same issue in Sola we have this common vulnerabilities but from now on how to improve my skills and get better on it so during my process of improving it I usually like to create diagrams of the project so while I start a new competition I start already drown the the diagrams and make all the fls
because um when you're checking the logic it's similar to eum so we will have some flow that will broke and then we can also learn some new patterns like how is a project a landing project in Solana after you read a code understand it you can easy look at another code and and matching those patterns if the pattern don't match probably one of them are incorrect incorrectly right and also searching for vulnerabilities you can do it looking at solo dat uh site or looking at old old uh competitions
report so we can also find all the vulnerabilities of a landing protocol searching for all the reports of Landing protocol you can have everything in mind and and then when you're going to make the next audit you are going to find it faster also make POC it's a good way in Solana I'm currently don't know how to make PC yet I know how to read understand the code but because PC in Solen is different from etherum like you don't use r you use typescript so it's completely different and in my opinion
hard to make it yet right uh so doing PC you can understand if if like the logic the flowing in logic you find it's really a flow because usually you see a lot of submissions that don't have PC and there is pretty obviously if you make one you could find that is not an issue or it's an issue and again put everything in practice I think this one is the best advice because while you were practicing and like I send one issue in a competition and then I I got a feedback
there was 15 issues so I learned from it where I don't find the issue how to where to identify the code of this issue and also have like a defined description of how this issue works right so following this and having a loop of searching understanding you will improve all of your skills and if there is one thing that I would like to guys remember from this presentation is that you don't need to understand everything at the first time
you could like if you have a full-time job and want to make a competition to learn about Rusty you get one try a little bit understand some part of the code some part will you will not understand but after putting everything in practice with some time like one two weeks you will see a good return of your knowledge so that's it it thank you very much guys I hope this presentation bring you my new ideas how to improve it and if if you have any question we can use it some minutes no good I hope I can explain
better everything thank you very much hi it's very nice to have you here and I want to ask a question you mention about the sonana P so how do you Fork a state of sonana and so that you can reproduce the hack all right I I've already searched about it how to Fork the state and like I don't think there is an way to do it right now I think there there is some complex steps that you need to do to to fork and state and work on it
so like most of the PCS that I've checked they create from zero like you have to declare everything like to create a state and then use it to try to break it so there there is not an easy way that I can for like similar to a you can just uh Fork using Foundry and execute something in the contract in salana you don't have it so you have to uh code it to make at to the that state yet I think I think they are uh working to have something easier to do
related to this thank you thank you okay thanks e e
okay um so for the second to last uh talk of today or Workshop of today um I'm I guess I'm deviating a bit of from the topic of giving uh defy security 101 introductions to like level more meta um what I want to talk about is uh the lean theorum improver um and you've seen lean actually in the uh in the talk about uh control um and this is going to be like a more more of a deep dive into the lean theover and if you feel a bit tired um I
can assure you I will um do lots of live coding and due to my state of mind probably will be make mistakes maybe that's going to be entertaining um so who am I um my name is Jacob I'm work for a I work for a small um defi company called Lindy labs and I'm basically working as a formal verification researcher there um my background is in type Theory and in interactive theor proving and in mathematics um and I'm the maintainer of egis um a small tool that we've so far only tested on our own source code it's a formal verification tool that can be used uh to verify uh contracts um
written in Cairo um Cairo is the language that powers the starnet L2 um and if I have time I will will um talk a little bit about egis at the end as some some some sort of example of what can be done using the lean theor Prov as a basis um but since I was invited to give a general introduction to uh lean um here we go first um so what is lean um lean is a project which has been founded in 2012 so roughly 12 years ago uh by a guy called Leonardo deura who had formerly been
working on um automated theorem proving I think you saw the uh difference between interactive theorem proving and automatic theorem proving in an earlier talk um and lenus on the interactive side um it's dependently typed um which means that uh the return type of functions can depend on input values broadly speaking um which puts it in the same class as other interactive theor provs like Co and ACTA if you know a little bit background but if you don't don't worry um this talk will basically assume no pre-existing knowledge about interactive theor improving um and it's both a a functional programming language
and a theorum um the theor is written in itself um it basically compiles itself and um that makes it autom automatically makes it a good tool to deal with programming languages and that's a bit of the gist of the talk that I'm I'm giving is that not only does it have like a proper good performance as a functional programming language not only can you trust it to be correct because it has a very small and easily verifiable kernel but you can also extend its syntax quite easily um and uh that's what we are going to do in this uh life coding experiment um and it's been designed with formal
verification in mind but also with formal mathematics in mind I think the biggest user group of lean is actually not people from formal verification but it's mathematicians who want to verify their proofs um and that ranges from like super simple stuff to like the most abstract uh complex stuff um and as I said this this talk is going to be like like one step more meta than the previous talks it's a I'd say it's the perfect tool to build formal verification tools on um barebone lean itself is not is not a formal verification tool because it doesn't have baked in um Notions of semantics of various programming
languages um so I guess I'll quickly go over some success stories of lean um one success story being um the so called liquid liquid tensor experiment where a Fields medalist mathematician was not really sure about one of his uh proofs which involved super technical arguments and um then uh called for help with the lean community and they managed to within a few months actually verify and simplify his proofs and that's kind of been the like starting um point for many of mathematicians being inspired to lose to use lean um and then a few stories from this year um AWS so Amazon um
uh uses uh uses lean to to do a lot of things because like the main developer is now working at AWS um there's a certified differential privacy library in lean um and maybe you've heard in the like broader media um from a of a project called Alpha proof um that's a that's a proof tactic for lean which has been developed by Deep Mind um that's actually been used to to um be so good at mathematic problems that it's actually solved a silver metal at the IMO at the international mathematical Olympiad which um if you know anything about the IMO is a pretty
pretty um great achievement um the lean ecosystem um mainly consists of lean itself obviously uh which as I said is self bootstrapping so it's written in itself um then there's a standard Library that's been managed by the lean user Community which is called batteries because it's like the batteries included version of lean um then there's the big monor repo that's uh that contains most of the mathematics formalization so that's called math lip um it does have a good package uh registry uh called Reservoir and it's called Reservoir because the package manager for lean is called Lake
um um so so far for for the ecosystem um if you want to learn lean um this hour obviously isn't enough to um give you any more than just a climp glimpse of what you can do with lean it doesn't it it actually cannot serve as a tutorial with just so little time um but there's a few nice resources there's a um a game that runs in the in the browser that's called the natural numbers game which um can serve as the first taste of proving statements with lean um in the browser without installing anything um so that's that's a first good step and then if
you're looking for more like a proper documentation um there's a um online book called theorem proving in lean and one called functional programming in lean which uh respectively highlight the use of lean as a theor improver and as a functional programming language um and those two categories are are not really um distinct because you can improve lean's performance as a theorum by writing your own tactics by writing your own Automation and um so you can use the functional programming aspect to improve the theor proving improving aspect and you can use the theor proving aspect to
do something like um um verified programming where you where the programs you write in in lean are actually correct by construction um then there's a good textbook called mathematics in lean which is obviously more aimed at mathematicians and then I think the best resource for any kind of questions about lean is lean's zulip server which is just a huge beehive of uh activity and um I think it's the most active uh zulip server in the world and it's should be the first point of contact for all kinds of questions you have on the lean theorem po um so yeah um like if I would give it um like a CR in one sentence I would say
that compared to similar tools lean strength is its extensibility for the syntax and its ability to pretty easily connect to external tools and that makes it a a good a good framework um to write your own formal verification tools um and so what we're going to do today is um to do a little bit of live coding and um different from the previous um live coding um demos that you've seen um I actually um mastered up the courage to um do it from scratch um I do have a GitHub repository where all the contents
of this uh demo um lie and I will maybe uh revert to uh restoring some of the contents from this um from this repo if my life coding deviates Too Much from the test runs I did before um so yeah what's today's agenda is that we will look at a very small example language um not a language that you want to would want to write any programs with um embed its syntax interlan and then equip um the syntax with a formal semantics so with a meaning inside lean um as a way to interpret um the effect
of those programs in the theorem Prov and then we will write a very very very simple um optimization for the semantics and maybe if the time is time remains also verify a super simple program uh written in this language okay so what what does the language look like that we want to embed in lean obviously we don't have much time so we can't um look at a language which has like 100 uh uh constructs so um the statements of the language um just fall into three categories there's assignments there's while loops and there's if else statements as you can
see with the two um examples shown on the right um we just assume the memory to be flat untyped and mutable so we just have for each string for each variable name we have one value um we have no types like we assume everything to just be like a um 32bit um um integer and um because we don't have we don't want to be writing down all kind of all kinds of binary operations um we just restrict ourself to two um to two expression formas which are just um apart from obviously constants and
variable names um a less than operator and an addition operator and so what we'll do now is um we call this language imp because it's a small imperative language um and our goals are now to embed the syntax of imp into lean and to implement um and prove correctness of a small optimization and um to then uh be able to verify programs we will also Implement a big step what's called a big step semantics um for this language if you don't know what a big step semantics is um no worries we will basically you will basically see on this example what it what that means
um okay so much for the slidy part of this presentation um now this is this big enough um is this big enough enough okay so um if you remember the first bullet point was um to define the syntax of imp um and what we would what we want first to do is to Define an internal representation of the syntax within lean um that means that we will um Implement what's called an as an abstract syntax tree uh of this imp language um and this goes by the means of just defining IND
inductive data types um that consist of all of the elements of this language thankfully there's only two basic constructs in the language namely expressions and statements and so we will have an inductive data type for uh Expressions which we call exper and an inductive type for statements which we call stmt um so inductive types form the foundation um besides functions of lean as a language and if you've not seen if you're not familiar with functional programming it's basically a generalized form of something like a a struct or an
enum where you can have you basically list all the ways of um creating of constructing terms um for these types um and so for the expression data type um we want to list four of what's called Constructors for this type so um remember that um for the Expressions we have constants we have uh variables um we have addition and we have less than that's all we need I mean we would need more to write a reasonable program but but that's all we want to deal with today so um let's first deal with constants let's just call the first uh Constructor const and um now we have to
list the arguments for this Constructor and um const should just take um a bit vector and because we maybe uh don't want to repeat our basic data type again and again let's define the type value as the type of bit vectors with 32 bits we could also Define uh like a program language with infinitely large integers and so on but okay that's what we're what we're going with in this example um okay so const should just take a value
V of this data type and then we need a Constructor for variables for named variables and we just want to um we just want to Iden identify them by their variable name so by a string um and now we need the two binary operations and uh the trick here is that uh these form what's called recursive Constructors so we have one of them that's called LT and that's got two arguments E1 in expr and E2 in expr so it takes two expressions as arguments and the same goes for addition note that we will just will
just um Implement LT as a um operation that just spits out zero or one just like in C for example okay so that's the um that's the data type for Expressions now let's Implement a data type for statements um the most basic building block is obviously an assignment um as we've seen here like all these lines that end with a semicolon and that equals our assignments um and what do they need as arguments they need a variable name on the left hand side and an expression on the right hand side so we again give it an argument s u as a string for the left hand side
and an expression for the right hand side um and then we again need a recursive uh Constructor because we need to um Cobble together several of these uh of these assignments or other language constructs um so we want to have some a Constructor for this sequential um execution of uh two statements so we have um S1 in statement and S2 in statement that will allow us to chain more than one statement together and now we have if then
else um that takes the condition that's an expression and it takes the then Branch that's a statement and it takes the else Branch that's also a statement and then we have y Loops which also take an expression and the body let's just call it B statement and now that we've Define these types we can basically internally represent uh for example the assignment where we assign I to Zero by um statement do assign
um what did I do and now if we hover here we need a string here so this would be I and this would be zero oh no this would be like the variable z uh no on the right hand side what would we want a con con and because it can't derive the zero we want to make this an abbreviation instead of a definition those are the so those are the details I actually didn't
want to talk about but those things happen when you do these kinds of things live okay so this is what we want to uh represent a statement in the in the Imp language internally um but we also really want to be able to write the syntax exactly in the way that I've presented it on the slides and that's now where the extensibility of the lean syntax comes into play um so the lean parza is this huge big thing that basically passes everything that I write into this editor and we can extend it live as we are going so we can extend the language that I'm using uh live basically and we first want to um for the paraa want to
introduce um new non-terminals for the paraa so we do that by declaring a new syntax category and we just call them the lowercase variance of those two those two things like one we call expression and one for the statements so that's new syntax categories and now we want to basically look at this and basically uh just build a parza for each kind of uh language element in here and we go through all of those eight Constructors now okay let's start with expression um so the first two are actually okay
I'll I'll start with LT and with ADD because they're may be a bit more intuitive and we just write syntax and expression and a less than symbol and expression that should be a new expression and syntax expression and an add sign it's a new expression and now for uh the variable names we just want to reuse the the syntax category that lean has for its own variable names and we just do that by by saying okay the identifier which I called ident in lean should also be an expression and we also want to use
numerals so we write new as part of Expressions okay so much for the Expressions now we need to do the same for the statements um okay the assignment um what's it on the left hand side we have a an ident and then we have the code colon equals and then we have an expression and that's a statement and I'm actually lacking the semicolon at the end of the line and this sequence is basically just statement followed by another statement
is a new statement and the if then else that's a bit of typing here so we have an if then we have an opening bracket then we have the condition um then we have the then clause which is a statement and then we have the else keyword and then we have curly brackets again and then we have that next statement and that should be a statement again so that's been a mouthful um and the same for the while Loops the while keyword and some curly brackets a statement should also be a statement okay um also note that this
would be the point where for the language we would set the precedences of um of uh for example for the for the addition so we could uh determine whether the addition would be left associative or right associative because we can write something like a binding strength here um okay okay so the next the next uh step might seem a little bit arbitrary because now we can we can uh we can form all these Expressions but we want to have a way to reflect them back into a syntax category that's already used in lean so what we do is uh we write syntax and then we can basically turn
every expression into a term where term is the thing um that um the syntax category that uh lean uses for all of the terms we can write down and we do the same for statement and what we can do now is let's check uh something like statement uh I colon equals z and then that's already good because it already has passed this and now we get a error message that just says elaboration function for this has not been implemented that just means that lean doesn't yet it can par it but it doesn't yet know how to equip it with
any meaning that's relevant for lean um we could also evaluate this and put it in in quoting brackets why doesn't this work um I want toate this actually or let's not do this okay so that that's that's for the syntax we saw the the arrow message so now we basically need to reflect the syntax that we declared to the abstract syntax tree so this is our abstract syntax tree and this is the syntax declaration and now what we what we want to add is
something called macro rules that basically take um something of this form and turn it into a uh into a term like this um so for example um we match um on a numeral then we just want to have expression. const um and then um how is
this okay now now my stage blindness sets in okay let's just start with a with a different macro um let's uh start with the addition so we want to this to oh yeah now we need we need to um surround this with um so actually what I completely forgot is that we want to have the brackets around
here 32 minutes and um yeah so I just noticed that this will take a while because for every Constructor I will basically now write one of these macro rules that will expand um the minimal form into the full um into the full form that's into that's uh of any meaning to lean and so I just did the magic trick of
restoring this um to not waste too much time on this um so we see that for every of the uh of the language Constructor we have one uh one of these uh macro rules um and now what we can do is um if we if we now check this then we see that x + y is less than Z gets translated correctly um to the as um so these guard methes here are just a wave to tell lean that it should um not
output the actual output of the next command but just check should check that it actually matches what's in the comment above that's actually quite a cool feature to um to embed test cases right in the in the file where you'd um Define them um so yeah now we can we can write something like this in lean so we've actually with just um okay it's like a two-digit number of lines we've just embedded a small imperative language U as some sort of DSL inside lean um and um yeah so we can write down programs and um have a representation in form of this um
as um obviously we still not really got like g g gave any meaning so that's what we um going to do next um let's uh next write a definition that actually evaluates an expression so it's an it's a function that takes an expression uh and should return something of the value doesn't it and since I restored this from the GitHub repository I'm know at a version
where I have not defined the value so we've do that again Val you say that this is bit vectors of size 32 and um actually needed this and now we've we need to go through all of the constructors of Expressions um so for constants uh this is super easy because constants already have a value and so we just evaluate them by returning this value um and then the next um let me leave out
variables for a while and go to less and then so less and then of X and Y and now we do a recursive call so we um just say that if eval of X is less than eval of Y um then uh one else zero now it's saying okay there's two cases missing the plus and the variables let's do the plus first um and that should just be like the evaluation of X plus the evaluation of
Y and for the variables now we uh we notice that what should we do with variables and um the way this is done that is that we need a a context of variables so we need U for the evaluation we need a mapping from the variable names um to the uh to their value and we can also like with the value here we can do a type definition and just say we say that context we can actually wrap it into own structure and say uh it should just consist of a maap for
Strings uh to Value so in a real programming language we wouldn't just have a map here but we would have something like a hash map um because we will always only store uh finitely many uh um variable names at Ed at each point um and now we can implement this we can say that okay the variable should be and now what do we have here um we still haven't any context so the evaluation will always happen if some in some context Sigma um and now we also have to retrofit the
sigma everywhere okay um and now this might also be the point where we um should um Define some operations on the context so for example getting a um the value given a variable name um be a value and that should just be oh because we need so we need a
context everywhere here so we can just say Okay this should be just be always Sigma should always be a context let write this here um and this should just be the map that sits inside the context and we should apply it to S and likewise we need something we later need something uh like set where we can assign something in the context to a certain value um and so here we need to say what the this should be a new Contex
text I shall say what the new map is and this is just if um so for each for each uh let's just call it uh S Prime so that's now a new string and for each and for each S Prime if it's the the name we are overwriting so if s equals S Prime uh then it should return V and otherwise it look up in should look up in the context
um the term at s okay um and we'll just in a moment uh prove some our first theorems about like getting and setting variables in context um but let's first uh complete the definition of the evaluation here um because now we have the context at our disposal we have a variable name let's actually call it s be a bit more consistent um also we've included this everywhere so we can actually leave this out
um ah no right we can't um so we need to look up in the context um what's it s um but we need to look it up in the context called Sigma um okay to test this let's test this actually um we also want a function that basically initializes a context to a certain default value maybe zero let's just let's just pick zero which should just be the context
where for each variable name it should just be zero now it says okay we have not used this variable name lean is very strict about uh using every variable name otherwise it will get you give you a warning um and now we can test this let's uh write eval of oh so this is lean's eval this is no like uh from a dactic teaching point of view bad bad namings but this EV is not this EV but we want to evaluate the function called eval um what context do we want to have we
want the context in in it and now we have to give an expression and let's just we can use this dot notation when it's clear what kind of type um a certain term should have I hope you see that on the on the right hand side um it's uh that's a very central point of almost all uh interactive fover it will show you the the the goal that we're about to prove when we prove something and it will also show you the type of the holes that we've uh put into uh into into the editor on the left um let's just add five to the
variable I and now we see that we've actually have the um yeah we have this bit Vector as a result so now we've interpreted um we've interpreted the um uh expressions in our in our programming language imp um so that's good um as I said we might want for later purposes um to actually have some theorems about getting and setting variables in the context we might
actually write our first LMA um and let's just call it context of get set same which should just be a Lama that if we um if we add a context Sigma get uh s uh s after setting s so this should actually be Sigma do set S V that should just be the same as
V what's happening there oh that's all um okay and um now we can type by and that that by keyword actually changes from lean's so-called term mode uh to lean's tactic mode so here will we we will be able to write a sequence of what's called tactic and tactics are basically a way of manipulating um the current proof goal um so this this is basically our proof obligation now
and every proof you will do in lean um basically consists of just a series of getting this goal closer and closer to something you can prove trivially um and in many cases you will be able to just call the correct tactic and prove it in one step um I will not have the time to show you any very um involved tactics today um but there's tactics which are basically implementing a best first uh treesearch there's tactics which um do um something like um smt solving there's tactics that are AI based and basically look at different proof structures and
try to recreate proof structure of your current goal um there's tactics that are very tailored to certain um to certain data structures for example um whenever we want to prove something about Rings which is very important if you do any cryptography verification um there's very sophisticated tactics that just normalize a ring expression for example um but so in this case obviously this Lama is is super trivial um we would want to call a tactic called simp which just simplifies stuff and we can give it a list of
definitions um that it should unfold so just say Okay unfold context. getet and context. set and then we get this this good error message here no goals to be solved um and with all of these interactive theorem provs they don't necessarily give you like a uh oh you solved all the goals message but the rule is basically if your if your compilation in the IDE goes through then you've um managed to solve all the proof obligations and and then in lean you have something like uh if we hadn't wrot written this we can write something like so something like sorry which basically
tells lean okay we are able to solve this but we'll not do it now we'll do it later um so yeah that's that's our uh first theorem and what we can do is actually tell simp to automatically apply this kind of theorem and we can just annotate the theorem with simp um and now we will be able to solve any kind of it will be able to reduce any of these any of this term by just v um so yeah you should always be always only do that if the left hand side of an equality is like more complicated than the right hand side of an equality
equality um okay let me look at my curriculum um yeah the next step I don't have much time left um but the next step would be maybe I'm just I just restore everything and then I just walk you through the code um um so yeah um we're now in a in a in the state where we've we've done all that we've proven those lemas um and now we want to write our first optimization
um and that optimization again for the lack of time can't do anything super sophisticated but what it can do is something called constant folding so if you have an expression um that for example in a less than expression or in a addition have constants on both side it can just already pre-evaluate um before running the program um and that's what constant folding does and it actually propagates recursively this kind of optimization it's a very uh weak optimization but it's it's part of every of every good compiler and so we can just Define that this as a recursive function from our
Expressions into our Expressions that just does nothing on constants and on variables and for example on less than of X and Y it just recursively optimizes the left hand side and the right hand side and sees if both of them are constants and then it replaces um it with the final result so this is a this is already something you could call a compiler optimization um and now obviously what you want to do if you're if you're writing a compiler um you might want to prove that um it doesn't change the outcome and for Expressions that would mean something like um whatever environment we have eval
valuating the unoptimized expression in this environment is the same as evaluating the optimized expression in this environment um and this again is a proof so we can say buy and then we get a uh a proof goal which is just what we stated um and then we can call a tactic that's uh called induction which it just um applies induction on one uh on one variable and now we see that we don't not only got one goal but we've got four goals that correspond to all of the four cases to cons varibles to plus and to less than and now we can actually add act on each of these cases
separately so this would be a very structured proof where you can actually you give case names and then for each of those cases um you find ways to actually get rid of all of the goals it's a bit like a computer game and if you play something like the natural number game um you can see that this can be very addictive to just hack away proof goals um obviously this again is a pretty trivial um trivial uh proof and you could also just solve this as a oneliner um either with a Tre search or by Just For example yeah just just just uh concatenating several
simplification uh tactics ICS um so yeah uh this is basically the proof that optimizing um with the function that we've defined here doesn't change um the value um okay um so how do we give meanings not only to Expressions but to entire programs um let me introduce something that's called a bigstep semantics so if you're um if you're familiar with formal verification or with programming language Theory U
you will already know this but um it's one way of giving um giving meaning to programs that are potentially uh non-terminating like the programs in our imp language because we could have non-terminating programs there we can have just have while one and then Loop forever um and because lean is a total language we can't just write a total function which tells us what's the um what's the outcome of running this program in this environment because it could never terminate and never give us an outcome um so one way to circumvent this when arguing about proofs um is to have a inductive
predicate so a predicate that takes an environment which is being seen as the starting environment uh the program which is a a variable of the um of the type stmt and an end environment and basically it's a it's a statement it's an inductively generated statement that tells you if I run the program if I run this program in uh this starting environment it will terminate in this end environment and and um so this is an inductive predicate so we will list a axioms that will tell us several ways of proving something about this big
step relation so it's basically a relation with three inputs like a starting State an end State and a program and um the uh Constructors for this relation basically looks like something like this if we start um in in a certain environment then the skip program which have I've missed and when I first did the syntax I just I just noticed um yeah so we just missed the empty statement the empty program which is super important because otherwise you can't um yeah um so if if you have this program and you start with the with a with a
state Sigma um then you end with a state Sigma and for example the sequential composition states that if you start in Sigma and the program S1 brings you to Sigma Prime um then if a program S2 brings you from Sigma Prime to Sigma prime prime then the sequential Co composition of S1 and S2 brings you from Sigma to Sigma prime prime um yeah if you stare at it for a while it uh seems reasonable [Music] um and the assignment basically says okay if you start in a certain environment then the assignment has the exact effect of setting this variable in the environment and here it actually calls
the evaluation function that we've written for the expression um then we have two cases for the if then else depending on whether the evaluation of the condition is true or false um and then the semantics for the while loop um are a bit more complicated they have one easier easier case for for the false case so if we evaluate the condition um and it returns zero then the state before the execution of the Y Loop is the same as the state after the execution of the Y Loop and if the condition actually evaluates to
something which is not zero so that means that we will execute one iteration of the Y Loop then we can do something which is called Loop unrolling which basically says that if the body of the Y Loop brings us from Sigma to Sigma Prime and then the whole y Loop brings us from Sigma Prime to Sigma prime prime and then the whole y Loop will also bring us from Sigma to Sigma prime prime um again this is maybe a bit abstract but it's like it's the way you can prove things about uh y Loops by continually unrolling single iterations of the while loop from the start and you will also like with like with
contract you will be able to um not only um prove statements about finitely many iterations of the Y Loop but by induction you will also be able to prove um what happens after an arbitrary unbounded um iteration of this y Loop um let me just show you um maybe this little example it just happens to fit on the screen um so let's let's write a super simple program that just um wants to swap the values that are in I and in J I guess that's
one of the like first steps you would do in C or something like that as a a kindergartner um and you would do that by taking a third variable Z and um um assign I to Z and then I to J and then you can assign J to Z um so you can actually do the swap by having one extra variable um and then we can for example uh prove that this actually swaps the two variable so for every for every eni to every pair of environments before and after the
execution um and the statement so this is in hypothesis thenan doesn't make any difference between hypothesis and variables that you put as assumptions for for theorems so these are just two two variables we want to the theorem to depend on and this is just a pre precondition just a hypothesis we want it to depend on so if um swap brings us from Sigma to Sigma Prime then it will have the following obvious effect um if we if we call if we probe if we probe Sigma Prime at I we get what Sigma gets us at J and if we probe Sigma Prime at J um we will
um get what's previous previously been I um and uh let's make this a bit more transparent so this is our proof goal and and uh so what we have to do is act on this hypothesis H um let's first just unfold the definition of swap in ag and now we've seen that we've have a little inline view of this little program here um and what we then can do is um again this can all be automated and just like for showing you what happens inside is if you if you apply a tactic called cases
on this thing then it will look which of the cases that we've listed atically above can actually um can actually uh be fulfilled in this situation in this situation the program just consists of a series of of sequential um assignments so we can perform cases once and now we see that here we got a new uh hypothesis which just concerns the first line and there we got a new hypothesis just which just concerns the other two lines um and because lean is very meticulous about variable names it puts these uh
gravestones to all of the variable names that we've not given an explicit name um and so we can perform these case destructions um again and again um and then it gets actually it gets very gets very noisy here um if I do simp it actually gets less noisy but still a bit hard to read um and now this is actually a conjunction so this is an end statement so you can write down Constructor and we get two goals one for the left hand side of the end one for the right hand side of the end and you can just call the simplifier and it will actually prove that this
actually is correct um yeah I guess that's as much live coding um as you can do within an hour um like obviously it wasn't all life coded it was hilariously optimistic um but so going from a like tiny toy language um to an actual language which is used in defi now that I've like two minutes left um just skipping over really quickly um so Cairo is the function as I said that runs Stark net it compiles through an intermediate representation called Sierra which is very which has a very easy syntax and it
always compiles through what's called a single static assignment form so we can very easily load this syntax like we've seen today into lean um and I've actually written this this egis tool which basically just lets you type into lean okay let's just load this Sierra file and it then provides uh to the user uh commands that allow allows the user to give a specification an arbitrary specification for each chiro function and to prove that this specification actually is correct and by the end you have something like e just complete which is you put it down on the on the last line of your big Theory file or of your number of the theory files and it basically checks that you've
given a specification and prove the specification to every uh single function that your smart contracts includes um and we've actually dock fed this to our own uh product so this supports Loops it supports the Cs calls in starnet um and we've um let me end on this horrible slide um in terms of in terms of design I mean not in terms of content so um our own our own um D5 Landing product has a white paper which lists a result from a mathematical
branch called control theory which basically con um implements a uh controller which uh determines the global interest rate modifier um according to the formula you see in the first line here you see that it's a nonlinear formula because it's got all these exponents and it got square roots and the white paper obviously implicitly assumes that we only deal with infinite prec Precision numbers in uh in this formula um and what we've done is we've actually managed to verify that if all of the variables which are in play here stay in reasonable bound then the entire update operation like
this is an update operations which which runs regularly on the contract um then the error the numerical error of this is Al bounded and so this is what this is the spec you see down there um and yeah we're beginning to um verify more of our own code and um we'll probably be ready to completely uh verify um arbitrary chiro cont contracts with this um and give it more uh assurances that um I guess no other tool can actually give because you can actually compare it to something like infinite Precision uh um numbers and um you can use the entire power of the mathematics that's been
formalized in lean to write your um specifications and your proofs and I think I'm over time and thank you for listening um I'm happy to take questions [Applause] afterwards e no thank you H hi everyone and I'm here
to show you a competition we're having at s Tor during this DSS so uh what we're having today h and tomorrow and the day after that um is a competition to build a smart solidity contract that matches um matches our work um in Sor but in Reverse so usually what we do at Sor um we write CVL properties and and CVL specification based on the code and design we get for our customers and that's it's hard to understand um if it's easy or hard to to start learning CVL so we thought H we save you the um scary work of writing CV CVL and just do
the other way around and just you develop the smart contract the solidity that everyone knows and we bring the CVL for you H so we wrote the CVL and for a smart contract that is a multisig and you write the solidity you just need a solidity contract that matches the spec the CVL that reward um the spec is very easy to understand it has properties of this contract we have a solution of course don't worry um and you just need to to run the approver and don't write any CVL you don't need to write you can write if you want it's very very nice and but you don't need to um so break break nothing as we like to say and the task itself um
you get a repository you get the link in a few minutes and it has a r me please read the r me H we worked hard on the rme it has it should have answers for all of your questions and if there is no if um there is something is missing there is a link there to lead you to a channel that has everything so don't worry um you get a few files multi. speec which has the rules um that describe the flow of the contract of the system we have an invariance dopc which is another CVL file that has a lot of invariance of the system for example uh we have an array of validators you will
see in a few minutes and we want to verify that they are always unique this array of validators so one of the invariance is that uh is that all of the validators H in any given two points are not the same always H we have a s spec uh which what it does is checks that you really implemented anything and what I mean is that if you start with the empty implementation that you get from us a lot of rules a lot of properties will just pass and you can run it by yourself and see and the sanity spec checks that you really implemented the features and because otherwise if you revert always then there is no case in which the property broke because nothing happens
any any time and never nothing happens ever so it just doesn't break anything and it's not interesting so that sanity spec is there to make sure that you're really doing something um if you want you can just ignore it and see that you can Implement something very stupid and it works so we check it and we have the state. Sol and that what inside we have the the storage variables so we can have um you know what what what you need to to use during the implementation for example the validators right that they showed they said about told about and we have also something regarding transactions and and more stuff there so look there and we
have the run.com um that is just don't need to change anything in it and that is the hard work we did for you so everything is packaged and just run sat run and run. con and we have the empty contract for the multisig uh which has only the external functions that should exist for you uh to implement the API and except from that like you can do whatever you want you can write whatever solidity code that you want can do whatever just don't touch the CVL because um we will run run it against our version of this of the spec which is the one you get in at the start so don't change it um so we recommend you to write um list of properties that is
derived from the CVL like for example I said the validators array should be unique um more properties of course there will be more properties um but you don't like if you don't want to you it's not necessity like you can do whatever you want but we recommend it H also um if you want you can write a short description about what the system should do H it really helps to understand what should happen and then you can start writing a codes it's like a real development process in really short amount of time like in two days you need to develop a system that is secure the way we know it's secure is because of the CVL and the way that we know it works is because of the CVL so should have everything and and it should
show you that if we write a good spec even before implementing it should be very F very easy and very fast to just Implement and you don't need to like you should test also your code but if you write proper rules you don't even need to test it because it's already tested with the CVL H then of course write the conf and solidity and run the pr and see if you're right or not um so notes H please read the rhyth me um I can't infen it enough everything is in the rhyth me um so the code needs to to compile and have comments so we can understand what you did um no bugs um of course if we
missed something or some property you think we missed please send send send to us H but I think it should be fine if something is not checked H then it's fair game you can do whatever you want and I know that people here like to find vulnerabilities so if you want to cheat you can try to cheat uh no hacking for other people but uh everything that approver says is okay it's okay so you can try whatever you want um I think we WR a good spec but you can chust and see um if not um and um of course make the code AS efficient as you can um because it will be important to us but first of all compile then pass
all of the rules and only then efficiency so first uh First Security then efficiency um so we have rules and invariance as I said um Your solution shouldn't take more than 15 minutes our solution is faster than that but it shouldn't take more than 15 minutes um and of course again don't change a spec file of course um if you want you can add more invariance to the spec file like if you need them because depending on your solution or your approach you might need more but and you can and you can add them and use them that's okay you can always expand our uh definition of the system or understanding of the system or maybe we thought that we don't need this invariance or extra invariance but eventually we turned out it turned out
that we need maybe in more efficient version of the code that we can prove is correct we still need those inance to prove them so if someone wants feel free to add whatever you want as long as it's invariant and you prove them um but we have a solution without uh additional invariant so we have everything for you you don't need to write CVL if you want you are invited to write CVL H it's similar to czy um okay so this is the repo if anyone wants to uh scan the QR um that's also the link um give you some time this QR should be everything you
need because the the other QRS um are should be contained inside of this so if I I think everyone scanned about another minute okay so this is for the support uh telegram Channel if some if something is not contained in the H in in the in the Ry the link for the this channel is also in the rme so don't worry um and I just remember that I didn't say about the um
right yeah what about oh yeah okay all of the rules about the rewards and about everything is inside of the r of course H as I said everything is in the rhy uh so uh good luck everyone ah yes reward yes so so uh the reward is inside of the rmy but I will say it so you so you will read the rhy H so the first three um groups or individuals that submit a verified spec H that is unique so don't copy like if you submit a couple of times we will just take the first one H so they win ,000 and we have also a bonus um for three rules that we
have and um that we chosen like it's in the rmy also H the the most efficient implementation of the of the of the code that will H solve those specific properties fast they will get $500 uh the the fastest ones H so of course in that bonus of course we also need to solve the other properties otherwise it's just I'm I'm not giving you the single rule to pass and then you can revert and that's it so of course we need to pass all of the rules and if you faced in that specific rule you get the bonus and you need to be the the total winner um to get the bonus H so good luck everyone and if if for any other reason or for questions or for anything
if you want to get reach me and this is my Telegram and if you want um and that's it good luck everyone and submission until the ninth evening okay good luck [Applause] okay how tired are you are you tired not
yet so tomorrow first first of all thanks all the speakers please thanks the speakers for coming and presenting great material H thanks to the wonderful volunteers helping us tomorrow we start early and we don't have breaks so please sleep well we start at 8:00 uh I know it's a bit uh early but uh we we have to be out by 6 uh we have a lot of things if you are student or somebody who's attended this 101 and have a problem in getting a ticket for tomorrow reach us we can uh solve the problem so please come on if you have a
if you are here and a student and you attended one one and you would like to attend the tomorrow and you don't have a ticket don't worry the reach up to the volunteers will help you if you attended 101 we we can give you a ticket enjoy and uh see you tomorrow e
e e e