Welcome to [Music] to I can start on the meanwhile. Yeah, sorry. Look at this screen. I'm Gorilla. I'm the CTO of Wonderland.
She's Lumi, a researcher at Wonderland. And this talk is all about best practices. Is everything we've been learning over the past four years and everything we've been learning from mistakes we have made on the past. So our main objective here is to give some tips and tricks or things you could implement in order to avoid making at least one of those mistakes. And if you can learn at least one thing that will help you improve improve your organization tomorrow, that's a win for us.
One more thing to note is that if you see any slide that might change your your life, but you don't get to take a picture, we'll share everything at the end. So don't worry about taking notes or whatever. Okay. So let's set the scene. You thought about this super nice new feature.
You coded it. You push changes to main. You got those thumbs up from GPT and you deploy it to production, right? You go to Discord and say, "Look at this. This is amazing.
You feel like a rockstar until you receive this notification and yeah, you got hacked." So, what was missing here? Obviously, a bunch of stuff. Yes, we got a nice idea. Yeah, we can pass the slide.
We got a very shiny new idea. Awesome. But not writing it down and not having a like a very good report of what we're trying to build will be a pain afterwards. Also, obviously, we pushed directly to main. We skipped any reviews.
We didn't have any audit. We didn't have any Yeah. pull requests. We didn't have testing. We didn't have anything.
So our goal here is to talk about what the process could look like if we would approach it security first with security as the top priority. Yes. Work. So uh we know that audits don't really guarantee security uh and safety in any protocol because if you take a look at the data last year over 70% of the uh of last year hacks were from protocols that had at least one file audited. And in 2024, Chainlink uh sorry uh Chain Light did this beautiful report where they logged more um 204 security incidents summing up almost two billion dollars and half of them were contract vulnerabilities.
The other ones were control hijacks, rack poles or governance uh attacks. So in order to prepare for this presentation, we spoke with several auditors and asked them, hey, what are the biggest giveaways of a lot of vulnerabilities that you're going to find? And basically, they all told us about the same things. So proper lack of lack of proper testing or overengineer systems was done that we one that we heard a bunch. Yes.
And rush development. Whenever the developers come and tell the auditors, hey, please start tomorrow and have it for next week or so, it means that usually they will rush themselves and thus a lot of bugs on the code are going to be found. This is a phrase that Joseline, ex blockchain director of trail of bits, told me a few days ago, which I think quite nicely summarized the whole topic of the talk, which is that TLDDR there's there's a huge gap between teams that take security as a proper step of development itself and ones that just take the last two weeks of the project before deployment and blindly give the project to auditors trusting they will solve any issues or they will find any issues. Who are we? We're called Wonderland.
We're a core development group. So, we help very cool protocols in the ecosystem, I'll say, solve their biggest and hardest challenges. Yes, we're a group group of about 60 developers, researchers, architects, everything. And yeah, that's what we do. So, uh this is a lot of information.
Where can we start? uh through the following slides we will discuss uh some of the points we think are like the starter pack to start a security first development. First of all, think twice and code once. For doing this, you know that when you're starting a new project, you have like this shiny idea, but you have to discuss discuss it with stakeholders, teammates, clients. You need at some point you need to actually set the specifications and for doing that we uh have the concept of an idea draft, which is basically a one-pager of the project you are going to step into.
In this document, it should be short, take one or two days after previous research. And here we will will specify uh the context what is the point of it which problem are we solving the scope which is what is expected to be accomplished during this project and of course estimations that we we will be like a little guess here but then in the tech design we will specify them uh better. So yeah, basically you don't need to follow our template, but uh the main point is that every parties must be uh on the same page before starting the the project to avoid situations like this one. And then we reach the tech design step. This is the most important and probably the hardest part of any project because it's where we translate the idea into actual logic.
And here we define every contract, every interface, every external function and how all of that talk together. And of course you said the flow of the system, the whole architecture and so on. One thing that usually happens and some auditors told us this when we were talking with them is that usually some of the main like architecture pitfalls are found in the audit and that's a late point to take action on it. So, one cool bonus here is to actually uh do a security check in the tech design. The the sooner we spot the red flags, the better it will be for the development and that way everyone stays aligned.
Awesome. Let's imagine we have our idea draft. We make sure we're on the same page, every single party. We have our tech design. We know how we're going to solve everything.
How do we we implement the test now? Where do we start? So testing it's literally like a Swiss cheese model where every single layer helps and you don't need to do everything but the more you do the safer you're going to be. I'll start with unit test but not go too deep because I imagine that most of you are already doing it. I hope so.
The goal of unit testing is just test one specific unit without any external dependencies. Right? So what you want to do is first not be guided by coverage because it can be lying. We'll talk about that in a minute. But second and most importantly test with intention really like even look at the tech design of what you want to build and write the test that you're going to do before even writing the code.
The closer you you'll get to DDD actually the better. I know it's hard TDD and everybody tried it and many people just yeah forget about doing it. Here for example coverage can lie. I don't know if you get to see the code but the example is very simple. There's two different returns.
So in this one if a is bigger or equal greater or equal than 10 you'll get to this one. If not you'll get to this one. So we might say okay awesome. Let's write test for them. And we'll write the test with 11 as an input and 100 and the second with nine as an input and 100.
Right? Also, we check the coverage. Everything works. But we didn't test with intention. We just look at the code and said, "Okay, how can we make this work?"
But we didn't think that if we were to input a as with the value 10, then what would we get? Basically, a nuclear explosion of division by zero, right? Coverage can lie. One other thing at unit test is when you're looking at the implementation you might end up something with the test that's basically doing the same. This is obviously an edge case, but you'll see many times in code, copy, pasted lines, three lines, two lines.
You know what I mean? Because I'm pretty sure you saw it before. Some bonus of unit test of things that you can apply immediately are for example buloko is a really nice one which I haven't seen used in many projects actually where it lets you define in human language every single test you're going to write and every single expectation and then it lets you scaffold all the tests for you. So that's a really nice hack. Well, fing the arguments, a very basic one and super useful.
Instead of writing a thousand test, you can fast the arguments and limit constrain those arguments in order to run your test many many times. It's not fussing, it's a different thing, but yeah. And this one also very important, mutation testing. Imagine in your code you're able to run a command and change every single symbol. Let's imagine for example a plus for a minus, a greater than for a lower than and then run your test again, right?
And if you change a symbol and no test fails, that means that mutation survived and then you're missing something. That's super useful as well. There is currently no support in Foundry. We're working on that. We have a PR open still in progress, but Slether Mutate is the best one we got till now.
Integration testing is basically the if unit was like mocking all of the external dependencies in integration, you want to leave them there, right? You want to test your code while it's talking with the AMM or the staking contract or whatever you're using. And this one is sort of the holy grail. And we saw for example Victor talking about invariant testing. That's pretty nice.
I would like to see more development teams like define invariance and actually test them. What is that? Basically, an invariant is a property that must remain true at all times. For example, the example we hear all the time, the sum of all the balances of all the users must equal the total supply that can never be broken no matter the amount of transfers you make. Right?
So, in environment testing, what you want to do is really define very very very good environments. That's the key of it all. and then try to break them and in order to break them you have different ways. So for example you have fussing which it's a stateful manner of calling many many functions in different ways and statefully try to break your invariant with a fusser or you can do formal verification basically converting your code and invariant into math that will later actually be able to prove whether your state can hold true. Last but not least is that yes our contracts must like could be safe.
We checked everything. We did all the test but whenever you connect them with your indexer or with your bridge or with your UI things might break. So even if you do manual QA or automated like end to end testing, please do so. Like yeah it's a very common pitfall and it's sort of easy to avoid. Yes, it's a lot and we need to admit that testing takes more time than the development itself most well always but it's really really worth it and I'm talking after we have deployed dozens and dozens of protocols it's very much worth it and now it's time to put on your auditor hat so uh we know that our code is public basically everyone can go check it find a book and if we ask uh any team or even to you of all the faces we have discussed uh where do you think security lives everyone?
Okay. So most of the teams will say of course the external audit sure uh but relying on auditors to catch all the books uh or catch every pitfall on your code without the whole context and so on it's quite a lot to put into a team right so uh instead uh we encourage all the teams to actually build an internal review process uh right after finishing the development and right before handing off the the code to auditors. the attacker mindset. I I mean you don't really need like a whole security team to do so. Uh even your own developers if they post coding and actually put their auditor hats and put on like the attacker mindset where they go and try to break things that's really enough and I mean you're already uh spending a bunch of money in the audits.
So if you can remove everything you can remove and make them drive crazy finding books, you will uh actually get the most out of it. So yeah, um it's important to treat audits like the actual launch and any high or uh criticality findings uh in the in the audit should be treated as a postmortem as well like should trigger uh like the initiative to write a postmortem. Um so yeah until now we spoke of a lot of things and it sounds like a mountain of um best practices but we want to talk about some lowhanging fruits that every team can adopt. It's not really rocket science. First of all uh branch protection rules as Gori said earlier uh even just like having the typical model of dev branch main branch both of them uh protected and so on it's enough.
Um, and for single commits, I'll open a new branch for every feature and request a reviews for each of them. That's already a lot. Then llinter. If you're not using one, bro, get the llinter. Basically, it will help your code look less messy.
And if you're working with a bunch of teammates, it will help even more. Lindspec is a nice one. We developed like about a year ago Natspec smells which basically we were getting tired of just looking at the nutspec and commenting in every PR hey you're missing this argument you're missing this return and so and we built a library that will check everything automatically we even found that uni before I think was missing an adspec and there was this guy Bib who came over and built another version which is even better built on rust so we're using his now we recommend you do as well and then we have okay comments like be specific, classify them, explain what you're doing, and use commit lint for that. And last but not not least, the PRs, keep them small. Anyone, nobody will review a PR that changed 1,000 files.
And that leads usually to plan approvals or not a full coverage review. Yeah. And one thing we mentioned before, but it's really really important is never rushing to deploy. Everything we discussed till now takes a bunch of time and it's the reality. The tech design obviously helps because you're being able to estimate way better once you know every single dependency and how you're going to build your project.
But still like we see such a correlation between teams that are rushing and teams that are up that it really makes no sense to rush the deployment. I just yeah I just want to mention this is our security team the leads of our security team and the ones who are thinking all the time how to keep us safer and safer at Wonderland and for partners and this is our team basically and this is like every best practice that we have is due to every single member of Wonderland being obsessed about improving stuff constantly. So this couldn't have been done without them really. Here we'll have like everything we discuss and even more we open source into a handbook. Basically our on boardings, how we learn, how we work with different protocols, our best practices, tips, everything is on the handbook.
So it's a really really nice read. I re I recommend and yeah and if you want to work with us, try to decode that uh or reach out outside. Yeah. Thank you very much. Thank you.
Round of applause, guys.
Automatic transcript — names and jargon may be misspelled.