DeFi Security Summit at Devconnect Argentina 2025: Nogal Stage, Day 1

DeFi Security Summit at Devconnect Argentina 2025 · 20 Nov 2025 · 7:35:46

Full-day recording of the Nogal stage on the first day of DeFi Security Summit at Devconnect Argentina 2025 in Buenos Aires. The stage's sessions cover compilers and virtual machines, including the Solidity optimizer, testing and fuzzing, mathematics and zero-knowledge proofs, and vulnerabilities, each led by a session chair with a run of short talks.

Speakers

Topics

From DeFi Security Summit at Devconnect Argentina 2025, hosted by DeFi Security Summit.

Transcript

This session is about compilers and VMs. As we know, a lot of the exploits have not been in the smart contract level, but in the lower levels. And our first speaker for today is Vladimir Kumalago, security researcher at Open Zeppelin, who will tell us a little bit more about the Solidity compiler and how you should actually use it. [applause] Hello everyone. Uh, today I want to pull back the curtain on something that most developers hardly ever think about. Uh, Solidity's optimizer.

Most of the time we treat it like a black box. We flip the dash optimize switch, put insane number of optimizer runs and hope our transaction get cheaper. But what is it actually doing on chain? Every extra op code, memory touch or unnecessary s load show ups directly in gas cost. And when you your contract runs thousands of times, those small inefficiencies add up fast. And the optimizer job is to maintain the original logic but lower the running cost of it.

By the end of this talk, you will understand how solidity code is compiled through both the legacy and via IR pipelines and what the optimizer actually changes from pip hole optimization to the deeper ule passes. We will also look at the optimizer bugs that have been found in the wild. First uh to understand the optimizer, we need to know where it actually sits in the compilation process. So let's start with a quick comparison between the two compilation pipelines solidity offers. the legacy pipeline and via IR pipeline. In the legacy pipeline, the flow is pretty direct.

In simple words, compiler takes your uh solid code and turns it into EVM assembly and uh at that stage, the optimizer model runs on that assembly and um applying various transformation to simplify it. Once it finished, the assembler turns into the final bite code. In the VI pipeline, the first step instead of gen generating KVM assembly right away uh the compiler translates the program into inter intermediate representation language called ule. The optimizer then works on that ule only that the optimized ule is lowered to EVM assembly.

uh and at that stage um the EVM assembly optimizer is executed on the EVM assembly followed by uh the actual transformation to the uh EVM bite code. As of today, the default if you don't explicitly pass the D- VIR uh is still the legacy pipeline, but the VIR uh the legacy pipeline, but the VIR has been around for quite a while. And Solidity team intends to uh make it the default soon. And what we are going to focus on next is what happens inside the optimizer box for both pipelines.

Before we dive into specific optimization, we need to say a few words about ule because it's the heart of the via IR pipeline. Ule is solidity intermediate representation, a small structured language that sits between solidity and EVM bite code. It has functions if for but none of the highle solidity sugar no inheritance modifiers or complex types. Why does this matter? Because ule is optimizer friendly. It has structured control flow. uh explicit jump targets which makes it much easier uh to analyze than row byte code. It enables whole contract optimization across functions and call sites not just local piphole tricks.

And as a very practical benefit, the via IR pipeline can automatically spill uh your local variables into the memory which is why you see stack to deeper far less often with via IR. So you can think of u as simplified structured view of your contract that opens the door to more powerful optimizations. But before all the fancy via IR magic, the there is a old school layer that operates directly on EVM assembly. The idea is simple. Uh piphole optimizer looks at tiny windows of EVM instructions and ask can I do the same thing but with fewer op codes or with cheaper ones? And here is um some classic examples.

And nothing surprising here. If you multiply if you if you multiply by zero, the result is zero. And the optimizer knows this too. Uh so when it sees op code sequences that computes something trivially, it replaces them with the final result. Some patterns are just cheaper ways of expressing the same logic. For example, checking whether a value is zero with equal x and zero is just simple the simpler representation is is 0x. So the benefit here is simple uh because we put only one variable onto the stack and then perform the up code instead of putting two variables uh two values on the stack and then performing the e op

code. And shifts follow predictable rules as well. uh shifting by zero bits gives you same value and shifting by more than a word size guarantees zero. The piphole optimizer recognize those cases and replaces entire op code sequences with a minimal equivalence. Uh the piphole optimizer also clean up after the stack uh when it sees us useless work. Uh if you push a constant onto the stack and immediately pop it, then the optimizer just deletes both instructions. Swapping the same two stacks elements twice gives you the original stack. Uh so those two swaps can vanish completely.

And finally here is an optimization that's very EVM specific. Uh if the code loads it open address and immediately ask for the balance the optimizer can replace that two op code sequences with a single self balance. Uh it does exactly the same thing but in one op code. And here's the interesting thing. Uh some optimizer passes don't just look at opcon in installations. Uh they track what values leave in memory and storage uh at the exact moment. Um you may ask why uh because once the compiler knows what sits in the exact storage or memory position uh it can sometimes compute expensive operations ahead of time uh during the compilation. For example, the

classic one is with Kchak 256. Um uh here we uh place a 0x FFF value into the uh memory slot zero. Then we compute the kit chuck of the uh zero of the value that's placed in the zero slot. And here's what the optimized assembly blocks uh becomes. Uh so what happened? Uh the optimizer mentally keeps a little notebook and uh recognize that okay memory at address zero now contains the value uh 0x FFF and nobody overrides this region before the hash since everything is now at compile time. This optim the optimizer simply computes the

K chuck itself and replaces the runtime hashing by the push 32 with the uh final digest. Now let's zoom out and talk about the ule optimizer which kick in when uh you compile with via via enabled and the optimize flag. Compared to the upcut level optimizer uh this one much more powerful because it works on the intermediate representation instead of uh looking at two three instruction at a time and potentially it can apply big changes and optimizations.

Under the hood, the Ule optimizer is a pipeline of multi multiple passes, each transforming the code while keeping the program uh semantically identical. Every pass tries to make the code smaller, simpler or or at least cleaner in a way that it unlocks further optimizations for further passes. And here's a interesting detail. The order of these passes matters. Some optimizations rely on assumptions created by earlier ones. So the sequence is carefully designed. The solidity team ships a default sequence uh of passes that works well in in practice. But if you really want you can uh introduce your own sequence and compile with with

this uh default u optimization sequence. Uh let's explore some of the ule optimizations. Um and first one is load resolver. The idea is simple. If the value already read from storage or memory and it's still onto on the stack, reuse it instead of reading it again because reading from the storage and memory is more expensive than just uh executing dupe or swap op code uh on the on the stack values. Uh here is a small example. Uh we have a storage variable a and in do stuff we use it twice.

uh once to compute uh a plus b and store it in the local variable c and once more then uh when we call the receive call with a and c. Now let's look at the via r optimized code for this. What's happening here? Uh a is loaded once uh from storage with s load zero uh and stored in the local variable a. the same value is reused to compute C and then when we uh prepare the call data for the external call. So instead of doing the uh uh two separate s loads we only pay for one uh load resolver notice that u there uh there is a a variable already on on the stack and we

can reuse it instead of uh loading it again from the storage. Uh okay let's move to the dead code eliminator. Uh the name is self-explanatory. Uh it removes code that can never be reached at runtime. If the optimizer can prove that uh a piece of code will never execute, it can just remove it uh from the bite code. Here is a small example similar to our earlier contracts. Um and here we place return uh before the uh external call. uh because we return uh before the external call the external call is unreachable and the optimizer is free to remove it from the bite code.

Uh here's a vir optimized version. Uh so so far so good. Uh we have u u the external uh we don't have the external call here. Uh the function now returns immediately. But you may ask uh why is a plus b still there if the result is never used? The answer uh the compiler must still generate the overflow check for the addition because this is part of the solidity safety guarantees. Uh even if the function returns earlier, removing the overflow check uh would change the contract behavior. An external call would suddenly be able to trigger and overflow overflow silently.

Uh and that would be incorrect. Now let's see what happens if we put the addition inside the unchecked block. Uh and now the addition disappears entirely. Uh we don't see it in the intermediate representation. We just return uh after the initial checks uh generated by the compiler. Uh because uh in uh unchecked block a plus b has no side effects and the result isn't used. So it becomes pure dead that code and it's it was removed. And the same thing applies not only for the return but also for other control flow uh patterns uh for example revert continue and break in

the loops, self-destruct etc. Next up is uh unus store eliminator. This one is also pretty intuitive. If the compiler sees multiple s stores or m stores operation writing to the same location and it uh can prove that the earlier uh values are never used it can just u remain the latest uh store or m store. And here is example. Uh in dust we assign uh twice to the variable a. First it's a b and then c. And the same works for the memory slot zero. Uh we put the value of b uh to the zero slot and then c. Uh but in both cases the earlier

writes are never used. Uh and the vir optimized version looks like this. Uh what happened? Only one store remains storing C into A and only one M store remains also storing C into slot zero. All the earlier rightes got optimized away because uh they were just never used. But now let's add an interesting twist. What happens if we place the external call between two uh s stores? Uh now we see two stores again. Why?

Because the compiler must assume that external call to fu might read a of the same contract. So the first write is no longer unused. The colleague could depend on it and therefore it can be removed cannot be removed. And uh the last thing that we will explore today uh from the ule optimizations uh is function specializer. one of the more surprising sometimes uh optimization because uh it can expand your bite code uh in a in a big way. Uh the idea is this. If you call a function with a literal argument and the optimizer u is allowed to create a specialized version of that function.

A new function where those literal values are hardcoded directly in the function body. Uh and therefore the specialized function takes less arguments. And uh let's look at a more complex example. Uh here we have a function fu that takes three arguments and hashes them together. Uh and also we have do stuff that calls function fu twice but with literal value of 10 uh as the last argument. And we have the do stuff function that just passes whatever the user provides.

Uh if we look at the via R output something uh uh we can spot something interesting. Uh here we have a uh a new function called funfu that takes only two arguments instead of three. And we see that sort m store places uh the hard-coded value 10 to the memory position. Uh and uh the do stuff function that is in the middle just reuses two uh the fun fu twice and the do stuff too has uh the uh f function in line uh into the implementation instead of using some specialized version of it.

Um so the specialization opens the door for additional optimizations uh and sometimes even reduces the bite code size but in other situation it just can expand your bite code and sometimes you don't want it um and uh there is some tricks uh of course you can just disable this uh optimization pass uh in the uh comp when you pass like uh the compiler input. Uh but uh if you want to preserve the uh default optimization sequence, you can put uh the trick into your code.

Um so here we have a stubborn function that takes u uh an argument and it returns actually the same argument if the call data is uh non zero and uh the usage is quite simple. You just call this function and pass the result of the function to um whatever function you want. But the interesting thing is that uh we just afuscated the logic for the compiler and and the optimizer. So therefore it will not be able to apply the function specialization. Uh so we don't have uh the function specialized. Therefore our bite code is uh smaller uh than we than

uh it would be with the function specialization. And of course there there are some trade-offs uh and there is no free lunch even with optimization uh you trade one resource to another and we don't we will not cover like uh compilation time. Yeah it's true that it will be much longer with via pipeline. Uh but there's also other consideration like potent uh like ones that uh you can potentially introduce back into your code. Uh but first let's cover the trade-offs.

There is inf famous optimizer runs parameter uh that controls uh that actually uh says how many times uh you expect each op code uh being run during the uh contract's life and if you put the high number of runs uh you say I expect this code to run end times and the optimizer is free to uh expand the bite code potentially but lower the gas cost. Uh and the same thing works uh for the lower runs. If you place lower runs, the bite code will be smaller but the execution will be uh more expensive.

Yeah, there is like hard cap for the contract size 24 kilobytes and also we have uh uh 200 gas uh per one bite of deployed contract charge uh that we need to remember and most of the time if you deploy a big protocol that will be used like very frequently uh it doesn't make sense for you to uh put the lower number of runs because uh your users will spend more uh And it's much easier to pay 200 gas per bite of the deployed contract.

Uh and now on the security considerations, um key rule for the uh optimizer uh that it should not change the logic of your contract. It should only remove or simplify things that are equivalent. However, historically there were cases when uh the optimizer introduced some bugs uh into the users uh code bases. So let's cover the first one. Uh it uh this issue was in the unused store eliminator that we covered today.

Uh and the bug u was present in the special conditions. Uh so first uh you need uh you had to write to the storage variable then you call some function on you have another code block uh that my exit earlier from the call using inline assembly like return or stop uh the return uh the return in the assembly block returns completely from the call not just from the function. uh and uh then uh the same function uh also has a path that returns normally and then write to the same storage slot. So here we have uh

assignment to x uh then we call the function g that has uh the condition that we just covered. It has a return from the function in case of a equals to true and there is an assembly return uh from the call complete uh from the call. And uh the optimizer looked at this and said like okay well after that call we eventually override the storage anyway. So the first right must be unused and we can remove it. But actually it was a bug because uh if we if you actually return from the from the call there was no right to the storage and storage uh remain unchanged.

And the second bug uh sounds simple. The optim optimizer incorrectly deletes uh memory rights inside an inline assembly block. uh the core assumption was uh if memory written in in line assembly block is never read at the same block then uh this memory is unused and we can just remove this uh m store. Uh however uh the problem arise when you have another assembly block that reads the uh exact memory location. So it's unusual pattern uh but sometimes developers use hardcoded memory offsets uh to place some values uh instead of using uh for example local variables uh to preserve it across the function calls

uh and uh yeah the problem was that u optimizer just uh was removing the first uh M store and therefore the value in the second assembly block was uninitialized or or if you had like uh some logic. For example, if you had a catch check in this uh call before the assembly block, uh it could use the scratch space. So, you would get the incorrect value instead of the uh 0x42. Uh to to wrap up, uh here's the big things to remember. U the optimizer isn't magic. is just a set of well- definfined rules and transformations. Uh

sometimes they are tiny like removing redundant op codes. Uh something huge, sometimes huge. Uh and it's important to understand uh how the optimizer works to uh write uh good code for for the optimizer. Uh and also u optimizer is extremely helpful but it will not fix your bad algorithms. It can remove an extra s load but it will not turn uh big O of N squared loop into constant magic uh constant time magic. This part is on you. Yeah. Thank you.

[applause] All right. Thank you very much. Okay. I'm Jeffrey from Rare Skills. I'll be chairing the rest of the event. So up next we have Joseph Ulutu Timaheen. He's a security engineer at Coinbase and he will be talking about uh his experience with securing L2s and VMs. [snorts] Hey everyone, can you hear me?

>> Okay. Uh, they're pulling off the slides. Um, but yeah, thank you. So, hi everyone. My name is Joseph Dra. Um, and today I'll be talking about building crosschain bridges across um, EVMS. So, um, brief intro. I'm Joseph Dara. Um, I'm on the blockchain security team at Coinbase. Um, specifically the protocol security team. Um, and, um, I guess we have, we've had a lot of blockchains since Bitcoin. Um, so far, this data is something I pulled from Coin Gecko, but it has 275 blockchains being tracked currently on Coin Gecko. And of those, we have like

89 layer ones, and we have more incoming. We have Temple, we have Monad, we have some that are probably still in stealth and all. And all these blockchains basically have like different ecosystem. They have like you know isolated um states which is not kind of public to other blockchains. Um because the way blockchains are built, the states are being isolated by default. Um and this brings up like some issues generally. We have like fragmented liquidity. We have like bad UX which is basically a feature of each blockchain being different. Um wallets are not compatible across some blockchains which is also a feature of how the blockchains are designed. And um

here we also have the issue of like CVL. So here we can see Ethereum has about 62% CVL um bitcoin and other things but these are what's about 10 blockchains with the largest top 10 CVL. But at the end of the day, we have so many blockchains and each of them are promising, you know, something great, something superb. They're promising the future of web 3. Um, but they all cannot work together. And what's the solution for that? Um, the solution is bridges basically. So, uh, today I'll be talking about bridges. Um, and then a few, um, details about like the EVM and SVM. So, the EVM is the ATM virtual machine. in

the SVM is Solando virtual machine and just a few bridge vulnerabilities and also talk a bit about the base bridge which is being built by Coinbase. So um basically what's a bridge? A bridge is a protocol that connects um different blockchains together. Um I mentioned earlier that each blockchain is isolated. So it's more like an island. And this vin diagram I have up here just shows how um blockchains are intertwined. They're basically isolated. Um so bridges are how you can actually con connect different blockchains um together and um there are different bridge architectures. So here is like a um will I say framework of how I can

visualize bridges. So we have your source chain your destination chain. We have a user on both ends and we have like an offchain component. So if a user wants to bridge using like a lock and mint branch, the user initiates a transaction from the source chain and if they're sending it cuz we had like an ETH event. So here they lock their it on the source chain through the bridge contract which emits an event and makes the call to um the offchain component. The offchain component which is basically validators. They kind of like verify the transaction and um lock the ETH and then also make the call to the destination chain which authorizes the mint of um ETH or wrapped it on the

destination chain which sends to the next address. And this is basically how um all lock and mint bridge work. And obviously through the redeem flow it's kind of the same thing just in reverse. So you burn your wrap it which makes a call to the offchain components which makes a call to your source chain contract and unlocks your ETH on your source chain. Um but this is just one of the architectures and I know like there are multiple um Ethereum is like an open-source um will I say protocol and basically everyone can be build anything they want and we have multiple bridge architectures also and these are just few I picked. So we have like a lock and

mint bridge and and burn and mint and then lock and unlock. Um the main differences between these are what is native on where. So um for lock and mint you have your native assets on the source chain and you just have like a wrapped assets on the destination chain. For the burn and mint bridge you have like native assets on both chain. So for example, if you have USDC um by circle, USDC is native both on Ethereum and on Solana and on B, but you wonder, okay, how do you say it's native? It's because it's being deployed by the same entity.

So they have the same contract, not just like a wrapped version on each of the individual chains. And for then the lock and unlock bridge, it's basically um a bridge that functions due to like liquidity providers on both chains where you like lock your liquidity in a pool on one chain, it unlocks liquidity on the other chain and we have examples for all of them here as well. Um, so yeah, a little bit of blockchain VMs and I won't be going too technical into like blockchain VMs, but basically blockchain VMs or virtual machines are the execution environment for transactions which um interact with smart contracts.

So anytime you send a transaction and that has to interact with the smart contracts, it's been executed by the blockchain VM. And um basically we have I I just have like a simple example here of sending USDC. So I know a bunch of security folks are here and they're ready to jump on like how many up up codes we have in just a simple transfer transaction. But this is dominate down into like just a simple flow. So a user is sending Alice and Bob. Alice sending USDC um to Bob. So Alice initiates the transaction and the transaction basically has a bunch of um things involved which is like a read um

compute. We have the compute of the actual um deduction and addition of balances and then the right um up code as well. So that's kind of like an slo um the computer and the s. But of course in like the native ERC20 transaction flow we have like multiple s losses M loads um and adds and subtract up codes in between and then the state is being updated here. So that's like a simple um what I say flow or example of how um transfers work um on VMs. But a a more um detailed um will I say information about VMs in this case is between the EVM and the SVM. And why I picked both is because um

the base bridge being built by um Coinbase is a bridge between B and the Solan and Solana um which is basically these two VMs together. So major differences between the EVM and the SVM um is how transaction is processed. So um the EVM is a stack machine transactions are processed sequentially um one after the other. Why Solana due to C level um basically offers um parallel processing of transactions if the same state is not being touched. So basically it's um examines the states that are being um touched at the beginning of the transaction and if the

same states are not being um affected it can process those transactions in parallel and I guess um we have like a new L1 which is also pro promising like parallel um processing for EVM and um another thing here is the state model. So um on EVM blockchains we have like contracts they hold both their code and storage in the same address while for Solana um which was much to my dismay when I started reviewing Solana contracts we have things that completely different so you have to assign a specific account for storage and handle those in a specific way that's uh adds another security layer over those and then um we have the gas fee model so

Ethereum uses the single um fee markets while Solena has like local fee markets. Um but this offers like some trade-offs between both of them. The first thing is um if multiple users are trying to interact with the same program which touches like similar states then obviously fees spike quicker on the SVM um and on the EVM if somebody is hosting like a large mint a large NFT mint um that could cause like a gas spike for the whole blockchain. Um, and these are constantly things that have been improved, you know, in one way or the other by new EIPs, new upgrades to each network, but that's how it works. And then for the smart contract languages, I

know we have a lot of languages aside and Viper. Um, Filogy was mentioning Sensei a a new compiler he was working on and we have like core solidity but it's all currently being compiled down to EVM byte code which is what um is being used by the EVM and um Solana compiles ROS to SCPF byte code which is kind of similar. So byte codes are basically um the list of the up codes and like the transa and how transactions actually being processed in this case.

So it contains all the instructions which um are being used here. Um so here I'll be going into um a few bridge vulnerabilities which are kind of like things I just highlighted which are things I highlighted in this case here. Um so one of it is kind of like the re relayer list. Um yeah so on the relayer side um relayers in this case are the offchain components. So you have like your two blockchains functioning. you have your source chain and your destination chain but um in between that the communication channel if it's being compromised or for example it's down so we had like a cloudfare outage a few days ago we had an AWS

outage um I think earlier this month or last month and if your bridge cannot function without that and there's no like decentralized signing um that can enable someone to like send or rather complete the message on the other side of the bridge you have your bridge basically trade down for some hours or some days and if possible like um it causes like loss of funds or some other risks. Um another thing here is real risk. So this is um something specifically complex to handle especially when handling like multiple chains. So time to finality is a big thing. Um here I highlighted this too but we all know time to finality on

Ethereum is about like 12 seconds. B is about 13 to 15 minutes. Solana it's about 13 seconds. Um and we have like multiple audit chains. ZK chains take a little bit of more time depending on what or how they are validating and um posting their batches. But time to finality is a big risk and if you have like rig happening in the blocks then obviously you would have to wonder okay how do you handle um riog risks such that you don't finalize a transfer of like $1 million on your destination chain and then you have the transaction riged on the other chain such that it never existed. And this is not exactly it it's something that could just happen

even trun like it's not an a direct attack vector if riot cannot be like triggered on the other chain but it could happen like a byproduct of you know some miscommunication or something wrong happening in between like each chains um and for example this is more prominent in like single sequencer chains um I know at a point when I started using the blockchain a bit um on Polygon. I I I had some issues with like Rio and stuff depositing to centralized um centralized exchanges then and um I guess that's was my first intro to okay how rigs could actually affect like real life usage.

Um and then again another thing is like replay attacks. So the function of the offchain component in this case of the validators is to like sign a message verified. So on your source chain you kind of you you've sent like 100 ETH um and then you are bridging that 100 ETH to another chain in this case um let's say another L2 or another like um L1 and in after the message has been verified and signed by the validators someone broadcast the message to the destination chain and you mint your 100 ETH but if that mint is not being tracked the signed message can just be replayed over and over again and And I guess um you

know companies like Open Zeppelin and other standardizations like standardized EIP kind of like help with this you know tracking your chain ID tracking nons um but if you're implementing something custom or on a chain that does not have like all these tools you have to like track um what messages have been signed have they been have they been used on the destination chain if you if using them failed how do you accurately track them such that they can be reused or the funds are completely stuck or how do you refund? So you have to handle that as well. Um so yeah I I think I did a simple um slide here of how like you send the same signed message over and

over again and that would continuously mint the same transaction in the same way. So yeah I another thing which has been um kind of the bane of web 3 is offchain stuff. So here is private key compromise. Um you have the social vector, you have like committing your private key to GitHub directly, you have multiple things but basically anything that can compromise your private key [snorts] is a big attack vector and which is why key security is kind of a big thing. Um you have to handle or you have to make sure your keys are not just you don't have like a single signer for your bridge for example. So if if you have like some uh I don't know like some

multiG where multiple people have to approve in different locations so you are not you don't have like a physical vector to your decentralized bridge. So I guess like there's there have been some examples the running bridge was pretty bad um and then we've had other examples as well over the years but yeah that's for private keys um issues. Now some bridge vulnerabilities um on the smart contract level. I won't be going too deep into this but we have basic stuff like re-entry. So different bridge have different functionalities.

Some bridges also enable like message passing where the bridge can make a a call to like a contract on be on your behalf. But if that enables like a call back then you obviously have like a re-entrance attack vector. Here you have like upgradeable tokens. Um so for tokens we have like multiple tokens such that like even the ER20 token standard is not being followed to the letter. Um and when you have like upgradeable tokens how do you handle the token balances of your bridges such that it doesn't just go to zero or like what exactly is your what I say backup plan or how do you remove liability the liability risk here for like upgradeable tokens for your protocol. And then we

also have like malicious message calls whereby you could craft a message that transfers the entire balance of the bridge to another um address. So some people handle this by you know white whitelisting um message calls or blacklisting some um function selectors. So you do not allow like special function selectors to um be called through your bridge. Um and then we have um decimal inconsistencies. So I'll just give a brief intro on this before I go. Um we have the B Solana bridge which kind of like connects B and Solana together. Um we enable different things token transfers arbitrary message passing. So you could say you could make a call to a contract directly from

Solana um from Solana to base. So you could basically call a deposit transaction on a base contract from Solana. And um we have like different security um will I say features which kind of like enable security. We have like validation of messages. Um we have a contract which kind of acts like the implement or your msg sender in this case which does the execution calls for messages being passed from Solana um to base and that is going to be mapped to every Solana address um as it seed and then we can enable like multi-token deployment. Yeah.

So uh on the base to solada side um we also have like validator verifying deposits. We have um you have to wait for finalization of messages um to prevent like the rig attack vector which isn't really a thing for Solana to base since we have like a shorter time um and also we can have multiple um Solana tokens for one base token. This is because of the decimal inconsistency. So if we have rust security researchers here, they know that on the Solana side, the way decimals is being handled and your max value is kind of different. We have the max of UN 64 in this case. So um UN 64 to UN 256 is kind of like a big jump. Um so here we kind of like enable

like multiple um token deployments with different decimal values while ensuring that this the tokens can always be redeemed on the other chain that it came from. So yeah that's basically um the talk but generally you would want to secure a bridge to like multiple audits. Um most of us here know what security is I would assume. Um but yeah, if you become a builder, don't just assume that your bridge is secure cuz you've built like because you've like audited other contracts and stuff. And then end to end tests. Funny enough, um I've audited multiple protocols where they don't have a full test of the full flow from transaction from like a first flow to

the last flow. Even if it has to spam through like multiple transaction, you have to test that to see if there's no leakages. And this also involves like fuzzing and all. I've spoke to many amazing teams that have like different forers, different state mutation testing and all. And um yeah, another thing is monitoring. So there have been a lot of talk about monitoring over the years. But monitoring is kind of a big thing. If you have any protocol including a bridge, monitor your funds, monitor your transaction flow, monitor anything you can monitor. The faster you catch it, the quicker you can react. And yeah, thank you.

[applause] >> Okay, Joseph, thank you so much. Up next, we have uh Giannis. Okay, Giannis is the co-founder of DDub. He'll be talking about how they diffused a compromised proxy. Thank you so much. >> Thank you. Well, well, that's not my slide. My slides will be there in one second, I guess.

Okay. Hi, I'm waiting for my slides to load. I'm Janice, co-founder of DOB. I'm going to talk about an investigation that we did uh last summer in July. It's a a joint investigation with a bunch of other people. I think this is one of the cool vulnerabilities of the year. So, this is very concrete. This is a specific vulnerability. Um, I see someone is still looking for my slides. You want me to connect my laptop? >> Okay. I don't know.

Yeah, of course. But still I'm sorry. That won't work.

>> That won't work. I'll I'll just use Yes, I'll use my language. Okay. Not my fault. I sent my slides 24 hours ago. Uh okay. So, this is on the CPIMP back door. Obviously a name we dubbed uh we dubbed the vulnerability CPMP to to make it kind of memorable. Uh again I'm Janes from DDOB. This is an investigation that's joined with a bunch of people. The the main people are there David Benol uh Seal 911 leader PCAO and Neville from DDOB and I'll give specific credits a little bit later. So what was this? Yeah, sometime in the summer, uh, David had, uh, pinged us before a couple

of times in the past about various vulnerabilities, but on July 8th, he actually says, "Well, guys, uh, let's look into this. I might have found something even bigger than before." And, you know, this is he was investigating something that was flagged by one of his colleagues, uh, Rashelon Casaparov, who didn't take part in the investigation afterwards. Uh but David had pushed forward and found a bunch of proxies that had been taken over by an attacker. So this looked uh a little weird. Now we all know proxy patterns, right? They're not even a thing from the blockchain. Uh they existed even before smart contract.

like traditional object-oriented programming. You have an object, it has an implementation reference in it and it delegates to an implementation. Clearly in smart contracts, we do it a little more in a little more sophisticated way. We use delegate call. So the storage is for the proxy, but the implementation can act on that storage. I'm going fast because I think you've all seen this, but just as a quick refresher, uh when the proxy is initialized, it gets the implementation reference. Later, we can upgrade to a different implementation.

That's the great thing about proxy patterns of various kinds. Now, uh with all proxy patterns, you have the proxy, it has an implementation slot, it gets updated. The big thing is that if you have not initialized the implementation, anyone can go in and initialize it to any implementation they want. So that's kind of a standard thing, right? And in most cases, that wouldn't be a big deal. That's no big deal. I mean, someone took over my proxy because they initialized it before I did. I'll just deploy another proxy. I didn't do anything. I hadn't even initialized it. So I'll deploy another proxy. So all you need to do typically is be careful to check that

the initialization when you tried to initialize it, it succeeded and then afterwards the implementation is your implementation, what you intended. Well, yeah. So it would seem it's no big deal. We found some proxies that were taken over. So what? Well, it was a little more complex than that. Now let me ask you, would you have been fooled if there was an attacker that before you tried to initialize your proxy, it was never initialized. It's just untouched. The moment you send your initialization transaction, your initialization transaction fully succeeds and emits an upgraded event that has your implementation in. So if

you're watching events, you think everything went fine. After initialization, if you ask the proxy what your implementation, it returns the legitimate implementation, what you thought you initialized the implementation to and you go to ether scan. You go to read write contract on etherscan and you say give me the implementation or it it prompts actually the implementation right on its own and it gives you your implementation. I think most of us would have been perfectly fooled by something like this and that's exactly what was happening here. So what's happening here is we have a proxy in the middle. That's the part that the attacker has taken over.

So we have a proxy. The implementation inside my proxy is the clandestine proxy of the attacker. This has been put in place by frontr running my initialization transaction. Again, that's kind of traditional, not weird to frontr run an initialization transaction. The weird thing is that this is completely hidden by most detection mechanisms. You will not be able to see this. So, this stays in hiding. It's owned by the attacker.

Anything that you call any legitimate functionality you call for the most part it gets forwarded to your legitimate implementation you ask what's the imple you get the legitimate implementation and in here there's a whole big setup of huge functionality because this is really a proxy that delegates to other implementations and it implements very complex takeover functionality as we're going to see. So dust has a couple of indications of the kinds of cool things that this clandestine proxy in the middle uh will was doing. First of all, it was preventing large large transfers.

It was letting small transfers go through. But if someone tried to get the money out of this contract, get more than 90% out in a single transfer, that one it stopped it. So it had like logic that prevented some actions but it allowed other actions. If anyone tried to upgrade to a different implementation, we will see the code. It actually checked and reinstalled itself. So this was something that had been going on for months. It was staying in hiding at many many services and we'll discuss that pretty soon. But the general structure is this one. We have a hidden proxy in the middle. So that's what we called the CPIMP, the clandest

clandestine uh proxy in the middle of a proxy pattern. Okay. So what were the signs that this was there that something had been taken over? First of all, the initialization transaction was front run. It actually emitted two upgraded events. It first upgraded into the implementation and then in order to fool you, it emitted an upgrade event o on the proper implementation. Secondly, the most telltale sign is that any transaction on that infected proxy, the proxy that now has been infected with the attacker's proxy has two delegate calls. So you call by bond maybe it lets you buy the bond. It it

was silent for the most time. Uh the the CPMP did not try to intervene in most transactions, but it had to do two delegate calls in the middle. first to the hidden the clandestine proxy and then to the final implementation. So those were the signs that would tell us that there's something in the middle. Okay. So we got the warning by David. Uh we had machinery to investigate the impact. Uh clearly in just a couple of hours it was clear that the impact is severe that many protocols on many chains were affected. So we called the war room. Who's better to run a war room uh than Seal 911? Nobody. Uh so this was

a war room uh by Seal 911. And we had two tasks right away. First to determine the impact. Uh I mean so we we had two tasks to find everyone who's affected and then to find the severity. And find affected for some chains was much easier because we have a database of everything that happened on those chains. So we could just write a query. For other chains, we had to watch events uh and write a scanner for blocks and it was not so easy. And to find effective just to give you an idea, the first query that we did was on the initialization transaction front running. So we just checked for two upgraded events. So that was not the greatest query. Uh so it was it gave

some noise. Uh the final query was a a bit uh like what I'm showing on the slide. It both checks transactions that have delegate calls and at the same time it looks inside the decompiled code of the proxy and we found a signature that was a telltale sign that the proxy was there. So we combined a bit of decompilation with a bit of dynamic information. In the end in a few hours for the change that we could support natively in our database we had very good estimates of the coverage. What are the protocols that are affected?

Okay. So I I know you were looking forward to this. Many protocols were affected and some were very very close to being exploited. Some large ones uh dodged the bullet by very little. Um so I'm putting some of the very large ones like Pendle and Origin at the bottom because they were like Origin was marginally affected. They had a a a contract on a secondary chain that was not used uh yet. uh Pendle, they actually had found out that something was wrong before our warning and they had managed to upgrade, but they did not know exactly what was wrong with their proxies or but they dodged the bullet

for sure even before our warning like a few day a couple of days before our warning. Uh so lots of protocols were infected uh on many chains and some of those we didn't have native support for. So this was a serious investigation to find out uh what was going on there. But that kind of gives you an idea of the extent of this attack. We have a hacker. We have an attacker who was laying in weight for months having infected many many protocols.

So once we figured out that this was pretty uh that everyone is affected or lots of uh protocols are affected, we had to determine the severity. That's not so easy. You see that someone is infected, but how serious is it? Well, maybe you cannot even tell if you analyze the code on one chain. So in one case for instance we saw that there was an infected contract that seemed to have privileges to send a cross-chain message through layer zero. Well we didn't know what will be the impact of a deposit message on another chain. Does it really give you funds right away? Uh so we had to communicate with the actual protocols

even before we knew how serious this was. And this made the war room a little complex cuz it means that there were some 10 different protocols in the war room and they all needed to communicate. They all need to coordinate. So, and imagine now you're a protocol. You have an attacker. Someone tells you your protocol has been infected for two months now. Well, you want to rescue your protocol, but then that same person who warned you says, "Well, don't act yet because that will warn the attacker and will endanger everyone else. Please wait a few hours until we can do a coordinated rescue. So this was complex to say the least. And every protocol needed different strategies for recovery

because the CPIMP actually had custom logic per protocol. It does custom actions per sector, per function selector. So uh you cannot just say I'll call an upgrade and replace. Well, if you call an upgrade, the CPIP will reinstall itself. you have to somehow say, oh, if I call that function that has no special actions on it, I can actually withdraw most of the liquidity from my protocol. So, I can put it on a new contract and I'm fine. So, many custom rescues were needed. So, this was a very hard war room. Uh, but for the most part, we had a very successful mitigation. In the end, we did uh there were a couple of protocols that were

missed, but compared to the overall impact, it was a fairly successful rescue. So before I finish, let me give a couple of ideas from the dissection of the uh attacker proxy itself. So let's go a little more technical. There's much more detail in in our blog post in our article. uh but we decompiled the proxy and you can get some ideas uh of its complexity. First of all, it's it was a proxy that itself delegated to intermediate implementations. So it could do any of a number of specialized things. So it could have customer protocol logic. So I already mentioned uh for most protocols it didn't allow

transfers that moved more than 90% of a token out from the contract. uh it had logic of course to restore itself post transaction in the implementation slot. It had logic for uh ERC transfer actions with permit with off-chain signatures. So even if you blacklisted uh the original sender, you could still uh do a transfer like the attacker could still do a transfer on L2s with uh off-chain signatures instead of st starting the transaction from a blacklisted address. So it had lots of complex logic and of course it was a proxy in the end. It just for the most part delegated to the original

implementation if it didn't have anything to do. And here's another very cool tidbit from looking into uh the actual attacker proxy. Here's how Etherscan was fooled. It wasn't so easy to for them to fool Ether Scan. So what in fact they did was they took advantage of Etherscan's policy to recognize implementations from many different proxy standards and they found an older standard and I'm sure none of you has seen this at least I hadn't seen it uh the or Zeppelinos proxy implementation. So that's an old proxy standard by open Zeppelin. So they

actually went and in that storage slot here they put the legitimate implementation. So Etherscan saw that storage slot that was not really used by this particular proxy standard and saw that and thought oh that's the legitimate implementation. So that's how Etherscan was fooled to report the legitimate implementation and not the the proxy the the malicious implementation that was in the middle. So they used something that obviously they found by lots of experimentation.

So this was kind of cool. Okay. So in all this was a major bullet dodged for the community. Uh this was a very sophisticated hacker that was lying in wait for months waiting for big fish to fry. Not just a couple of million that they made away with in the end, but something much much bigger. uh and it was very successfully mitigated. It was discovered before it was exploited but it was definitely a very sophisticated attack. Uh lots of people deserve credit for this. Uh so David Benimol uh obviously the the original reporting original find and lots of investigation

in the days of the war room. uh Seal 911 uh PC Aversato obviously led the rescue effort, coordinated the war room and actually investigated the ether scan fooling technique and then uh from our company Neville wrote the queries over the impacted protocol and reverse engineered uh the code of the malicious proxy and there's more technical detail but I think you got a pretty good idea. This was a sophisticated proxy in the middle that was waiting to to get big fish to fry. Thank you very much.

[applause] >> I left room for questions, right? >> Yeah. >> The nation the intention. >> They were waiting for tens of millions to go into one of those protocols. Like for instance, if they could have hit Pendle, if Pendle had used those contracts before uh being discovered, before the attacker was discovered, if had used that those particular contracts and had major liquidity, they would have

attacked. It's one of those like how we saw with a by- bit hack, right? you they took over something extremely major. They took the safe they took over the safe UI but they got one big fish in the end. So they were waiting for something like that a lot of liquidity in one of the protocols. >> Peter. >> Yes. >> Yiannis were any of the users with approvals targeted at all or drained? >> So So >> were any of the users who approved to the protocol like infinite spend drained at all as part of this attack? >> Uh no I don't think so. I don't think we had lots of approval vulnerabilities in this in this attack. I don't think it was there was it was approval based.

>> Were there methods that could do like arbitrary calls to do the drain on users in the in the back door? >> If you could do arbitrary calls with uh with those I mean I I'm not sure that there were any approvals at all to those proxy contracts. So I think obviously if there were approvals you have everything in the middle you can do you can do anything you want there. Uh so I think there were no approvals or no major approvals anyway let's say so that's something that they may have waited for for instance one of those contracts using actually transfer from in the implementation and getting approvals and then they can do anything.

I'm curious how do you you find it because it was a pretty high attack. How >> I mean if someone is watching transactions it's not uh it's not so hard to find because if you're actually dissecting a transaction at the very least you can tell there are two delegate calls or if you if you watch your initialization transaction very carefully you see sometimes you you clearly see that it's much more complex than you expect. like it does initialization two times here pretty much. So it's not unnoticeable. It's like who pays attention to those details? If the events are right and it does the thing that I want, why would I go and trace the transaction? But

someone did and then the impact was estimated. Yeah. >> Sorry. >> It's not initialized twice. What it does is it it's initialized once to the malicious proxy in the middle. So it emits the upgrade event and it emits a second upgrade event in order to fool the legitimate implement. So the legitimate deployer. So it's not initialized twice, but it sets two references, right? And not only it sets two references, it also emits two events just to fool you, just so you see the legitimate event. And then there's another one.

By the way, the estimate is that this was not in North Korea. This was uh the estimate based on various things is that this was uh uh China some Chinese hacker group. Thank you very much. [applause] All right. Thank you. Okay. Up next we have uh Charles Cooper. He's the lead developer at Viper and he's going to be talking about differential fuzzing.

>> [applause] >> Hello. [snorts] >> This is the remote. >> Oh, okay. >> I'm going to use my computer. Actually, >> we have your presentation. >> You can do what you want. Well, I'm going to use my computer. Hello. Um I'm Charles. I'm actually

subbing in uh for our security engineer who is going to present this a different talk but then um he got sick and so I am giving my own talk which is also on [clears throat] differential fuzzing but it's about AI decoding. So uh first of all why does that show of hands who knows what AI decoding is? Okay great. Um, AI decoding is extremely hot in the compiler. Um, you probably don't think about it much, but [clears throat] whenever uh contracts, excuse me, contracts call each other on the EVM, they follow a a standard [clears throat] called AI encoding and

decoding. It's a serialization format um along with some other things, metadata and stuff. But anyways, [clears throat] excuse me. Um, AI decoding is the part where you decode data that's been encoded by another contract or in call data or maybe in code or data somewhere and you want to basically deserialize it into your own local memory structures. And there's something that's very interesting about how AI decoding works. So AI the AI spec defines two kinds of data. One is static data. So that's stuff whose length is known at uh statically. So for example, a unit 256. Everybody knows it's always

going to be 32 bytes. Um and then there's dynamic data. For example, a bytes type which has a dynamic length. It can it's variable at runtime basically. [snorts] So the way that AI the AI uh defines the data layout is it puts all the static uh data in one section and then where there's dynamic data it includes pointers to what's called the dynamic section. Uh so for example if we have some bytes uh this is a tpple of bytes by the way. So because it's a tpple, the AI defines one static field which is the location of the bytes data in the dynamic section and then it has the dynamic section which is kind of

a reasonable encoding of bytes which is the length uh word and then the data. [snorts] Uh a more complicated example is a tpple of a tuple of bytes. It's recursively defined here. uh and because uh I'm able to use the formatting with the bullets, you can see the recursive structure actually. So you have the static section of the outer tpple uh it points to this dynamic section. So the inner tpple of bytes is defined as a dynamic data structure and then you have this thing which is the inner sorry the static section of the inner tpple and then that points again into the dynamic section of the bytes or sorry the dynamic section of the inner

tpple which is the bytes and then you have the bytes data. [snorts] So uh why is AI decoding hard? Uh so this is from the AI spec, the solidity docs. Um and this is how it defines how to write a decoder. And you'll notice that it doesn't really say how to def how to write it. It says uh you could have a strict decoder which basically expects uh the data to be uh encoded in the way that the this canonical encoder that I just kind of outlined. Or uh you could be a little bit less smart and then everywhere you

see a pointer in the static section, you just follow it. Um, and so you don't check if the pointers are valid. You just kind of keep following them. And uh, we'll find out why this is kind of problematic in a minute. Um, but why is this a useful property? Um, the useful property is that sometimes people like to have kind of clever encodings of their data. So here's an example of like a tpple of two bytes. Uh, and this user is very clever and because the data is duplicated, you only need to uh write out ox12 34 one time and then in the static section where you have the pointers to the bytes data,

they point to the same location in the dynamic section. And so it's kind of like aliasing. So you can define very clever or interesting structures. Uh I'm getting looks from the audience uh where you you don't really uh encode it in like the obvious recursive way which is like encode this then encode this then encode this. You can have like weird pointers in out uh up around in the payload. Um the other reason why this is a useful property is because the implementation can be more efficient if you don't actually check that the data encoded is like super strict like each uh element is followed continuously by the next

element and so on. Uh you can do again what I just said which is like follow follow the pointers. [snorts] Um so we've had this implementation of just like following the pointers for a long time. Uh and this uh was reported as a bug by uh Alex Wade a long time ago which is that uh when you decode stuff from call data or when Viper decodes stuff from call data we don't check that the pointers are valid and this is like maybe a problem because like uh here where I where we have uh yeah this is a simple example here this pointer could be invalid. It could be like ox a million and then when you jump

to that pointer or to the data where that points you just like get a bunch of zeros in the call data. Um so at the time we analyzed this and uh closed it because call data is always user controlled. So like even if you can force the compiler to like read like some pointer where it doesn't exactly expect uh you can't really do anything because it's just pointing to data that you also provided. So it's not really an issue. Um so when this this start to become a problem is when we implement the AI decode built-in. So AI decode is a user uh facing function that AI decodes a buffer of data and the

difference between this AI decode and the built-in call data decoder is that this operates on memory. So, uh, this is a very interesting bug. Um, because, oh, you can't actually see the, um, I wonder if I can open this actually. You can't see the the Y which breaks this. Oh, yes. Excellent. So, this is the call data which breaks it.

And basically uh you convince it to read data from ox which is outside of the payload uh outside of the y-buffer. So the way that these are um laid out basically you can force it uh to read data from outside of y which in this case we mutate it in between the invocations to abide code. Um so that's a kind of weird thing [snorts] right that's pretty uncommon.

Um oops how do we open this again? Control F5. Oops. Whoa. Okay. [snorts] Okay. So, that's kind of weird. And uh this is what's called a talk to apparently. So basically uh if you can force convince the user to like it's time of check versus time of use. So if you can convince like some poor developer to write some code that AI

decodes the same data in between there's another memory right then there's like this weird bug. Um okay so this is like just the start of the journey. So then we like started to fix this bug uh and [laughter] these are some commit messages uh involving some fixes and the whole thing is very tricky and I don't want to get into it too much because of time and also uh it's a little bit inside baseball but basically um you run into a few problems uh one so for example this is an there one of

these is an optimization So like when you notice that the length is zero, uh you think that you can like actually check some of the recursion in the um ABI decoder, but you actually can't because you need to check that some of the pointers are valid. Um so and then there's other weird things where you're doing pointer arithmetic. So the user if they provide uh some attacker payload can force some like arithmetic overflow actually in during decoding. So there's all these kind of like weird pointer things which can happen.

Um and by the way we fixed all these within one 10 minutes. Uh we fixed all these within one release cycle. So these were like we like did some fixes and then we like went through them and found some other issues. Um so eventually what we realized was that we actually need a spec. So we want to allow uh stuff like this which users think is uh important or interesting. Uh but we also want to uh basically avoid bad pointer behavior. Uh and the way we defined it is so here uh this is not even a recursive thing but this is

recursive right so basically the pointers are currently allowed to point anywhere uh and as I mentioned with the call data uh that's okay because the user controls all the data so what we ended up deciding is that we allow these arbitrary weird pointers that aren't like necessarily pointing to continuous things but they have to be within the user provided payload. So you can jump so from this inside thing you can maybe jump out here, you can jump up here, you can jump up here but you can never jump out of it.

And uh along the way we kind of realized that this is impossible to like test, right? Uh which is why this is a fuzzing talk. Um, so yes, so this is what we ended up deciding on. And um, I wonder why this slide is wrong. Is the slide wrong? No, it's not. Okay. Uh so this is so eventually we decided that in order to test this we needed to write a simple implementation in Python and this Python uh implementation is basically the spec and the reason is

that the compiler code for the AI decoder is full of stuff like this. It's long. It's probably hundreds of lines. It's one of the most complicated parts of the compiler. Um and it does all kinds of weird optimizations for different cases. uh because the code is so hot, it really does need to be fairly optimized. Um so what we did was we wrote a spec implementation which is this and it's here and basically it's supposed to be as simple as possible. Um maybe I'll pull it up if I have time at the end. Uh and then we fuzz it. So we we check that the spec implementation decodes data the same way that the

compiler does. So we take the same data, we feed it to the spec implementation and we also feed it to the compiler and see that they give the same result. Um why is this actually interesting? Um the interesting thing is that doing this the naive way where you just like feed random data to both of these um you know implementations doesn't really work. And the reason is that the input spaces is is absolutely massive right like if you take that bytes example that's like 128 bytes that's like uh I don't know what 8 to the 128 is the size of the input space and also like the any given pointer which is something

that could be a problem for us during decoding is a unit 256 and that's like a huge thing we could like run this until the heat death of the universe and never find a bug. And I just did this naturally because I think about the heat death of the universe all the time. Um, so here, so we we noticed this, right? We start running the fuzzer and we're like, it's not finding any bugs like uh and in fuzzing like you don't want to be like biasing the fuzzer too much. You don't want to be like, oh, but we're not finding any bugs, so there must be something wrong with fuzzer. But like it should kind of be finding known bugs after some amount of time. H and if you think about it conceptually like it's

not going to find bugs like if you just provide a string of random bytes to this one of these things or whatever uh it's just going to be trivially invalid, right? It's going to be a trivially invalid AI payload. So there's a couple techniques we used. Uh one is mutating valid data. So you take a valid AI payload and then you kind of point mutate it or you do something weird. You uh take a chunk a slice of 32 bytes and rewrite it into some other 32 bytes. um still weren't finding bugs.

And the reason for this uh is that conceptually when you think about the AI decoder, when you think about it for long enough, I'm probably not in the first five minutes, but eventually you're like uh g- whiz, uh the only hard things in the AI decoder are actually uh these pointer dreferences because everything else is straightforward and a unit 256 is just like you copy 32 bytes. You can't get it wrong. uh when you decode the bytes that's also just a copy. You can't really get it wrong. The only tricky thing is like ensuring that all the user pointers are valid. So uh we started doing something which I consider a little bit clever which is uh kind of making the AI payload as full of

uh up pointers as possible uh like poison pointers. So we like bias the fuzzer heavily or not that heavily but a little bit. Uh and this is actually the part of the fuzzer which does it. Uh to when you do the point mutations to kind of draw from things that could be valid pointers or they're like maybe just outside of the range of the valid space. Uh and this is uh interesting because it introduces the concept of like high value data. Uh so I think the kind of uh yeah so this is very interesting right?

Uh so here's the important part. We take the for the um data that we're going to point mutate with or like the word you take it and it's kind of bounded by the length of the payload. And like anything in the range of like minus length of payload to length of payload* 2 or something is probably like a reasonably good thing especially with like um integer overflow. So this checks like all kinds of things. checks out of bounds overflow off by ones. Um, yeah, I probably have like three minutes left. So, I think the takeaway is uh that you kind when you fuzz, you kind of want to have an idea of what values

are high value, what things are high value, what things are poisonous to your program and kind of try to guide your fuzzer towards those things. um you don't want to do it too much because kind of the point of fuzzing is also to find bugs that you don't know about. But if you have some idea of what is poisonous to your program uh then uh which is funny because we're talking about snakes viper uh then you want to kind of bias your fuzzer a little bit with those. And uh here's our in the interest of time have to stop. Uh here's our GitHub Telegram group. Uh any questions?

uh no actually [laughter] >> it's it's still running >> please. >> So uh I miss what fuzzing technology do you use? Well, yeah, there's a library in Python called Hypothesis, and it basically lets you combine different strategies into larger strategies. >> I I I don't know specifics, but I do know that uh AFL, which has dominated fuzzing for the past 12 years, supposedly had exactly this motivation to be really good at finding uh serialization bugs or bugs in big binary buffers uh as input. So I don't know if hypothesis is AFL based uh which is kind of this the library that now many

languages use for fuzzing. If it is uh I'm a bit surprised but I don't know enough. So maybe it's completely natural like you said it's very hard to fuzz those things. >> Um AFL is interesting because it's coverage based right and uh when we're fuzzing the compiler what we're actually interested in is the coverage of the generated binary. Uh and it's like not that easy to create uh uh coverage based hooks for AFL for the EVM bite code. Yeah.

>> Uh okay. >> Sorry, my bad. I I just wanted to ask you if you have some thoughts on how you would improve the developer experience of generating custom mutators for fuzzing from your own experience. >> Oh uh that is a really interesting question because um so if you see here uh the mutation uh routine is kind of weird. you like draw from the way I implemented it is you draw from like a list of possible actions and then you apply those actions to the original payload like uh edit add uh delete whatever word um and um that's actually

really slow because the way that hypothesis works is it like creates some weird a full of the possible actions and then it like traverses it so it's like not it doesn't really feel native. Uh so I have a lot of thoughts about that but maybe we can take it offline. Thanks for that. Um, is there anything in particular you were using or techniques to uh identify whether the the fuzzer was making progress >> and like >> that's a good question. Uh, so uh basically we would run it against like various commits and see if it found bugs and it actually uh was pretty effective at that.

>> Yeah. Um, >> but say if it's running for a day, like there's no flame graph or like, you know, if it's running for a day, it's always the problem of maybe if I just run it for a day plus one, it'll find the thing. >> Yeah. Uh, that's uh one of the things that's really hard to reason about with fuzzers, right? Is like what kinds of inputs have you already done? It's really unintuitive. Uh, what kinds of inputs have you already tried? What kinds of inputs are you going to explore next? Uh, like what is the input space and how do you traverse it? Uh so that is one thing I wish we had uh better visibility on. There's like debugging facilities in hypothesis uh which kind of let you inspect this but it's really manual. It's not like an amazing beautiful dashboard. Yeah.

Okay. I think we're at time. Thanks. [applause] All right. Thank you so much. So that wraps up this session. will be going into a break and uh be following the rest of the schedule. No, no, no break. Oh, we're jammed up right against time. Okay. Uh okay. So, Al Alex Oh, he's behind the pillar right where I can't see him. >> I'm sorry. I'm taking over the chair so >> to see you. Thank you.

>> Okay. >> So, no break but we're going to continue in the session of fuzzing and testing and we are going to start with Alex from Get Recon is going to talk about going beyond 100% coverage. Yep. One second, please.

There we go. You're mirroring. Be careful with what to show. >> No, this is all on purpose. >> All right. >> Awesome. All right. Thank you for having me. I'm Alex. This talk is called going uh beyond 100% coverage. Uh very briefly about me. I run a audit company that specializes in stateful fuzzing um for DeFi. We are EVM only. I um um used to be a developer. My smart contracts handled hundreds of millions of dollars.

And from that I decided to I decided that fuzzing was uh uh very helpful for security. And so I basically started recon with my co-founder Antonio Vano. Um my experience as a researcher uh I basically have about half a million dollars in uh bounties and contest wins. And this year thanks to stateful fuzzing I prevented a critical exploit on Ethereum mainet. Basically saved the protocol and prevented $20 million from being stolen. Thank you. And uh yeah, if you want to check what we do, we do effectively audit powered by invariant testing and we also have a platform to run this type of test in the cloud and soon we'll uh do our best to fully automate that

thanks to AI so that nobody has to maintain this test anymore. So this talk is about uh coverage. So uh I'm going to take you past 100% coverage. But before we can get to that, we need to uh get to 100%. So obviously there's many definitions to coverage. It could be line coverage, branch coverage, modified decision and condition coverage. But for the sake of argument, I'm going to use some new terminology that hopefully shows you the idea visually. I'm going to also show you uh one of our internal tools related to that. And so even though coverage is not the holy grail in the sense that you will find all bugs, it is still the best metric we have to

measure our progress. and uh we would evaluate both formal as well as concrete tools based on their ability to test various combinations. Therefore, it's not the full picture, but it's a very good guiding function for progress. Um I'm going to quickly construct this idea of a coverage class. U we're going to quickly see them. So if it's a bit too abstract, don't worry. I'm going to dig deeper. But fundamentally, given a function, we're going to take all the storage values that can influence it. We're going to take all the inputs and we're going to create some sort of a mathematical group where we have the storage combinations and the union with all the possible inputs and we then specify all the possible coverages that

derive off of that. Therefore, we can have three types of coverage classes. We can have a non-reverting coverage class which is what we would use to explore state and explore combinations. We would have a reverting class which for the purpose of fuzzing is not particularly useful but it could still be useful to identify the service attacks. And lastly we would have an assertion breaking coverage class meaning a um set of inputs and states that would lead us to break an assertion. This is the type of targets that we want to hit for invariant testing. And uh if these ideas sound roughly similar it's because I didn't know that other people already wrote about them. You can likely find them in the literature as extended EPAs, extended enabled preserving abstraction

or as the idea of modified condition and decision coverage which is how NAZA tests its own uh software. Uh but the key idea is really we analyze its function. We look at the preconditions, the various states as well as the inputs that will reach that specific coverage and we group them together because symbolically and mathematically uh they belong to the same group and um so when we want to visualize them I'm going to show this internal tool called the um the liner and basically I have a simple function here from liquid governance and you can see that we have various paths.

This is very similar to how a symbolic tool um will think. We basically have a case in which we have zero votes. So we have an early return. We have a case in which we have non-zero votes and the payout per votes is non zero. So we will cover the entire function. And then we have a scenario in which there are there are non-zero votes but we also have zero um uh total votes and I think we got a revert or something like that. And obviously this becomes insanely overwhelming. You can see a very small function from liquidist governance again. Uh and this this will probably drive anybody insane. I'm not advocating for you actually doing this but I'm advocating that as you u formalize your auditing process. This is how you formalize it. This will guarantee that

you have effectively went through all the combinations. And so even though this is uh a superhuman I wouldn't define this as um impossible nor useless. So as I said, I would suggest this is how I would say that an auditor could quantify that they're done and yet we will still miss bugs. So the takeaway from uh thinking about coverage classes is that formal tools as well as fuzzers could visualize their progress through these uh v um UX uh stuff and they will basically show us the progress that they're making. Obviously the uh real holy grail of coverage will be puff coverage. Uh meaning you try all the

combinations symbolically for all possible inputs. But fundamentally even just having the ability to know that we export certain of these combinations is a massive step towards in terms of improving the developer experience as well as the ability of uh guiding the fuzzer or at least getting some feedback from the formal uh tool which at this point would just tell you that it uh timed out giving you no particular actionable insight. You can read more about the uh my my notes. uh this is a GitHub repo I open sourced and it will likely continue to change as I read the literature and think about this more. So this is kind of the let's say the uh more academic part of this whereas

now we're going to uh go into the more pragmatic uh aspect. So the key question is really why can we hit 100% coverage? Why can I give a any tool a fuzzer formal tool etc the ability to explore all these states and I can still miss bugs? This is really uh the the key question and uh as I said even symbolically we could explore all the combination and still miss bugs which leads us to the fact that uh coverage is insensitive to the bugs. Uh and more specifically, it's the equivalent of you going on a hike and uh being so focused on just making it through the hike that you miss all mushrooms, whereas somebody

else that is more experienced can enjoy the view and can fundamentally pick uh those mushrooms. So my uh intuition is that obviously code is math. we can express coverage as a set as a system of equations that we have to resolve and therefore bugs must also be a property of the math that we're looking into. So I don't really have a exact answer. I can't point you to a formula to find a bug. But I think we can all agree that if you have a system of equations that gets you to coverage then you have to do something to that system of equations in order to find the bug. There is a missing piece there. And um over time I think we're gonna zoom in into a few types of bugs. Although obviously we may

never be able to find all of them. So as I said symbolically the you have a formula. So likely there is a more complicated formula that is basically uh exploring less state space. And so if coverage if what whatever gets me to cover this is a elegant formula then there's likely a uglier formula which is likely the intersection between the formula that gets me to coverage and some other property that will lead me to a smaller state space and basically will lead me to the interesting state space and bugs which is kind of what we do as auditors and as such uh I think there's a big parallel between this idea

symbolically and then this idea uh uh pragmatically. So um yeah, my key insight or my key thesis this year for this talk is that for the for the purpose of um you know making you think and giving you something actionable, we're going to effectively extend the definition of coverage by adding more to that metric. Meaning that we're still going to use coverage which as I said is blind to bugs. So it's still fundamentally a faulty approach. it's a um we're we're likely to still miss bugs. However, as we introduce more effectively more lines, more aspects of the code as part of the way in which to evaluate coverage, uh that that gives us a chance

to uh miss less bugs that um that that effectively match with this uh framework. So this is the key um idea uh fundamentally uh this is from academia um having a uh high coverage doesn't strongly correlate with finding bugs. However, having a big test suite that effectively chunks the code into various components does correlate with finding more bugs. Meaning that if you normalize for test size, meaning you you just take the minimal set of tests that will lead you to coverage, you are actually coverage is not particularly effective.

However, in practice, just effectively throwing a bunch of stuff uh into your test is is uh is actually fairly effective. And so the real the key idea is really we're going to uh extend coverage by adding new lines. And I'm going to talk about exactly these lines. So this is where this becomes a bit of a esoteric talk, a bit sci-fi. Bear with me. Hopefully the journey is worth it. So the first level of new coverage or extension of coverage will be implied lines, which is the idea that some lines of solidity imply other lines that either the compiler is adding and we're not seeing or that are executed through the node. A uh a pretty good example

would be message of value or a token that doesn't return boolean such as USDT. These lines of code are implied by the code that you're writing. So when you write a for loop with message of value uh being sent in a loop, meaning you introduce a fairly simple bug, the the lines that you're that you're supposed to be covering, the lines you're supposed to be testing for are in the EVM node. As such the um coverage the way we measure it which is just line coverage or branch coverage on the contract is completely insensitive to that because it's not accounting for the fact that that code is covering those parts of code and as such if we add a

way to incorporate that we will find bugs. Another great example would be a overflow where a overflow is effectively the operation or it happens because we introduce a value and then the compiler automatically inserts a mask to alter that value. As such, if we add an explicit check for every overflow that no truncation is happening or no alteration is happening, we will be able to catch all overflows at all times whether they're useful or not because some overflows may be done on purpose.

But what I'm really saying is that the compiler like uint 88 of a u 256 is implying a truncation and we as the human we are uh blind to it but the code is actually there we're just not measuring it. So I feel like this is the most realistic example uh of an implied line. We're going to get more esoteric as we go down the list. But hopefully this again makes you think about how we could measure this better. So as I said message value obviously the line is only here it's just this uh uh line but what's really happening is account dotbalance minus equals etc in the node and we're also getting the balance etc.

And so th those lines exist we can all agree that they exist is that our methodology is blind to it. So this is actually solvable by simply writing better tools. Uh same for a c20. The reason why I put the year C20 is because I want to do a quick detour on star. The idea uh of star is the idea that a call uh could be done arbitrarily to any address. And this is something that auditors will hate you for because fundamentally a star means that I have to audit for anything and even formal tools just over approximate when whenever that happens. But uh this shows you the danger of star because a star

meaning an arbitrary call to an arbitrary address implies that you have to cover the universe for the line. It literally means the amount of lines that I would have to add to my coverage is infinite. So it's the definition of something that can be addressed. We call it constraining behavior and it's simply the idea that if I'm doing an audit, I want you to provide me with the list of integrations and then I want you to hardcode them. Ideally, just hardcode them, make the system immutable or provide me with a system that will ensure that those are the only integration you will interact with.

Because as I'm arguing, if you want to be fully certain that of the security of your system or at least you want to get towards that, now you have to add all of the lines from that contract into your coverage. Like that's the only way for you to measure the actual effectiveness of test against that. And anytime you mock an integration, you're basically uh asserting that that uh system can be simplified down to that. And uh most of the time that requires more work. So constraining is a key aspect and is a very common reason why we get bugs like like the an example will be the pre-ompile bypass. There was a signature scheme that didn't account for the fact

that a pre-ompile will effectively return true and that's an example of having a star where now as the auditor I have to think of every possible combination every possible pre-ompile and that can be just too much. So you're much better off hard- coding those options so that way your coverage can reach that hypothetical 100% and you can own that code as well. So now we're going to enter the esoteric zone. So this is science fiction. Uh all the terminologies is made up by me. So if there's uh uh any reference in academia, please share because I I'm eager to learn. But fundamentally the next level is what I will call implied state which is something that happens for example in re-entrancey. Re-entry implies that a smart contract can be in a different

state. There is no storage value. There is nothing that describes that state. However, that state of execution is different behaviorally and semantically from the normal state of execution. The state of execution that we tested for. And so my argument is those type of bugs can be described by implicitly adding a storage value to the contract and then considering the coverage of that contract when that storage value is altered to be a different one. So an example is uh fairly straightforward is obviously we will fix this by adding the norra modifier. But you can see how simply adding a boolean flag and then asserting that anytime the withdraw

function is uh called with a different boolean flag. This is a different function and this is a different coverage will ensure that at least mentally we are considering those type of combinations. Obviously there's a million ways to avoid this. we will go back to the idea of constraining behavior. We would rather not have to think about this and so we would abide by check effects interactions. However, sometimes your system can't do that. And for that reason, this is the type of logic you want to apply. You want to think about these implied lines that effectively uh would better describe the uh the inaction state of the system. And so if we could just magically uh go into byte code and instrument it and put

various boolean flags, this is how we would go about analyzing contracts mid execution with these new types of states. The next level is meta properties and this is effectively properties that we use for uh invariant testing whether it's formal or uh concrete. But the key idea is that we take the system under test. We poke at its state which could be uh the actual uh state or the aggregation of various states. And so what tends to happen with meta properties which is particularly interesting uh based on the discussion we just had is that the meta properties is basically cutting reality or cutting the equations in a different way and is giving you the sensitivity that we're missing when we only think about

coverage. And that's because a good example would be if you have two variables. Say you have a sum of two variables where one variable and the other variable can be of the same magnitude or one variable and the other variable can be of massively different magnitudes. If you have a meta property that describes that state now uh how uh you you can now see when your system goes through a state in which one variable is leading or a state in which one variable is not leading. And so a class a classic example here will be perhaps describing the relation between uh shares and assets in a vault or other form of mathematical operations uh such as uh for example the relation between a

fee and the principle and so you can see how uh a meta property will make it so that not only you have the a line I don't know if I have code for this but I basically spoke about this yesterday I did a live um event where I was uh fuzzing is Mark an oracle and I show that because from coverage alone uh fuzzing the oracle would uh lead us to finding zero bugs and zero issues and then by adding stateful fuzzing and then looking at uh manipulating the price. the that property was basically cutting reality was creating this intersection between the formula of coverage and the uh the formula of the price and in that way we were able to see a 50 millionx

price manipulation and so sometimes it's literally a matter of distinguishing between the magnitude of two variables and it can make all the difference in the world um and so this is the code you can check again the the talk I did yesterday it's on uh DSS YouTube channel and so the last one that I have for is world splits something that I don't fully understand but fundamentally um because zed is a group uh it's not a group zed is a ring and uh we basically deal with integers then we have to account for the discrepancy between our perceived the perceived behavior of math which will be mostly linear mostly well behaved and what you know I drawn here in uh in two seconds to basically show

what we would call a step-wise alteration And so these type of uh alterations are how we find most bugs. This is my my favorite bug of this year. I it's in my um audit report for liquidity v2. But basically that uh truncation right there led me to investigate the ratio between b b b b b b b b b b b b b b b b b b b b b de debt and batch shares and it led me to find a way to borrow for free on liquidity. And so fundamentally all I did though if you think about it beside obviously a lot of effort was really finding that step. And so in conclusion the takeaways are we can improve fuzzers we should use these ideas to better uh show our work. And uh I just want to

give a massive shout out to my team Nikonor and not for uh helping me build the stuff that I showed you. Thank you for your attention. [applause] question. >> Thank you. uh when you're fuzzing in EVM land, are you ever considering uh like a system of contracts or is it always

single contracts in isolation? Uh you can watch me uh practice what I preach in the uh talk that I gave yesterday. that we always deploy one target contract that then deploys the system under test as well as all the target functions we use to explore state. So it's a very complex issue but fundamentally it's one target and then we manipulate the target to explore the state of the system under test. >> Thanks again to Alex.

>> Alex >> [applause] >> Yeah, for the system under test, how do you define the types? Like do you put on the system of equations? >> Well, uh the the system of equation is something you want to reason about and formal tools already do this, but they do it at a lower level. What I showed with my internal tool is we uh create a system of equation on the solidity directly. So we heavily um simplify the system but the key takeaway from the the talk is that you should be um exploring that more so than telling you exactly how. So find a way for you to generate

those equations and you will find more bugs. >> Okay. Thank you. >> Okay. Thanks again to Alex. [applause] Our next talk is going to be from Ysef Gatamaya, CEO of Ake and he's going to talk still about fuzzing and how to close a circle from machine to human and back and forth. >> Thank you.

Okay. So, uh hello everyone. Uh I'm happy to share here our view on uh fuzzing. I tried to do a little bit like a summary what happened in the last year and I tried to balance it like uh to be very neutral but show some of our alpha how we do it. Uh so first of all like why we are here why why is uh fuzzing uh a problem? Of course when uh we are fuzzing smart contracts the main issue is at least from our point point of view the number of integrations which makes the state space very huge. If uh the space state space was smaller uh it would be easy to just uh fuzz it by

brute force or if any one of you had a uh quantum computer we would not need to be solving all these uh fuzzing techniques but we are not there yet. So uh the statement is just that uh the state base is very big and the question actually is like how to find the bugs in the state space and I completely agree with uh the previous talk that uh the coverage uh the percent of the coverage is not the thing that uh helps to find the bugs that's not the metric. So we just need to focus on the techniques that help us to find the bugs where they are and not to be fuzzing that space that basically gives no value for the fuzzer. And the first let's say set of tools uh I call that like machine driven fuzzing uh in this category fits the

black box gray box and it's basically something that you set up and let it run and the machine does everything. Uh so of course into this category fits like a medusa and this kind of stack where they are based on the two main uh techniques which is covered coverage guided uh feedback loop and then some heristics that is trying to cut also some part of the state space. So I guess you're familiar with the concept but basically like uh coverage guided feedback loop works on the principle that uh uh you put some random uh random transaction you see then uh where it got in the state space and then you are favoring uh the path that already that explored the

new code path and you're iterating over that uh over and over. The heristics it's something that basically uh is trying to uh give some more information for the fuzzer so it can make a better decisions which can be for example coming from the static analyszis uh such as slitter and it can give some concrete addresses or it can give some uh very edge uh values that also help the fuzzer to explore the states that are uh probably containing the bugs.

So the advantage of this approach is that you set it up, you you uh let it run. Uh it's very effective in finding uh finding some bugs that the auditor would not think about. Uh but the disadvantage why basically like we uh were not going by this approach uh is that sometimes the auditors they have some idea they have idea where the bug could be and what we wanted to achieve is to be able to test this idea by the fuzzer easily not wait if the heristics or uh the state space exploration drive the fuzzer uh the direction that we want it to be. So that's the reason yeah sorry uh so exactly like this limitation

of uh this how we call it machine approach is that the real bug can be hidden in some kind of like chain of events for example like 10 events that have to follow each other and it's very hard for the uh horistics to get there. That's why we tried to do it a little bit differently. And the second uh part is like uh human uh guided fuzzing which uh we create a methodology we call it manual guided fuzzing and it kind of like explains what it is. So basically we wanted to give the power of guiding the fuzzer back to the hands of the auditor and not rely on heristics or uh coverage guided uh fuzzing. And

basically how it works some of the principles are the same. So there are invariants but what we introduced kind of like the new thing uh is called flow and you can understand the flow basically like an integration test uh which is telling uh which is defined by the auditor and is telling the execution path where the fuzzer should go which is exactly uh can be the complicated 10 steps that have to be done in the protocol in order to test the happy pass scenario. Uh so this is the key part of the methodology and then we have uh because we like Python so we always like implement in uh Python like a model of the protocol. It can be just a part of

the protocol for example accounts. And then what we do is that we compare outputs from the fuzzer uh and outputs from the uh contracts from the outputs of the Python state. And of course it should be even uh how does it look? Uh here's a very simple uh code snippet of some uh simple bridge. So basically uh we can see here that we uh create a Python state as the first two lines. Uh this is the local state that we are tracking. Uh so the model can be as simple as this and then continues the function uh flow deposit and bridge and this is basically the core of the flow. Uh it's uh there is a

flow decorator which basically tells this is the function that we will be randomizing for example 1,00 times. And in this function we have some uh built-in uh built-in for example features like random account. So we select the random accounts we select the randomness then we execute the transaction and the first check is that we just uh have the state uh stateless check to see if the event was emitted successfully. So this is nothing sophisticated. It just shows that the implementation is correct. uh but the fun part begins when we here manually update uh the python state. So basically here we updated how we think the protocol should behave and then we

define the invariant and invariant is executed after each flow. Uh and in the invariant basically here we just compare that the state of the uh of our implementation equals to the state that's returned from the contract. So this is kind of like the easiest uh example of the manually guided fuzzing as we have it implemented in wake framework and by this basically we are giving the power to the auditor which means the auditor has to have the idea how to create this kind of like u happy pass scenario or how to create some attack vector scenario and the fuzzer just helps to test it on all accounts with all possible inputs and this kind of like randomization stuff which means

in the huge state space we are not trying to cover the whole state space but we are just like very selectively selecting the path where we think uh the bugs are and of course the advantage is that we are leveraging the domain knowledge from the auditors. So basically the auditor has the idea that the fuzzer helps to execute. Uh but also we observed one quite interesting thing and it's that during the implementation of the fast test because we have to implement the model uh sometimes the auditors find the bugs that the fuzzer for example would not uh discover. But by forcing the auditors to think about the protocol and implement some of the

logic of the protocol in Python basically it opens the mind map in the head of the auditor and this process helps to find the bugs. So also like one part is the bugs from the fuzzer but one important part is the bugs that help to uh the fuzzing process helps to discover. I have some numbers here. So basically most of the issues that are discovered by the auditors when they are writing the fastest are the lo logical errors. So we have here the issues that we discovered in the last I think year. It's only high and criticals. So almost half of that are the logical issues. So this is the stuff that that is explored when writing the tests and then we have here like data validation service and this is the

typical stuff that is discovered by the fuzzer. So even the process that we have is like helping to uh discover the bugs. But there's a problem of course this is very time demanding because actually like we are little [clears throat] bit like a rewriting the protocol in Python. Uh so of course uh there's a lot of manual work for that a lot of boilerplate code and also when anything changes in the contract we have to rewrite the model which is something that the clients or the protocols who are paying for our time don't really uh like. So we are thinking like how we can maybe a little bit reduce the overhead reduce the costs and that bring us to the third category and it's like again

taken control a little bit back to from humans to machine and uh we try to do some AI assisted fuzzing which we of course named wipe fuzzing and here we are trying to combine basically the two words together uh because the manually guided fuzzing works really well But there's a lot of mechanical work. So the question is like if we can kind of change it to focus only on the security logic and not on the boiler prey code. So we tried and the good thing is that v framework has a documentation and we we we also have some playbook there with lot of examples. So basically when you open cursor and just put it to the context you know set up local uh local environment and just tell the cursor

that check out the documentation look at examples it pretty much learns the framework and then we are basically able to uh generate the boiler plate code by LLM. So all the loops event handling and stuff like that is generated but of course it's hallucinating. So the important stuff needs to be checked by the auditors which in this case is mainly like the asserts. So what we are asserting because sometimes the LLMs tend to be checking things that does don't make any sense and also we need to check that the implementation of the updates of the Python model are correct and also the auditor is usually the guy

who has the idea about the execution branch or the happy pass scenario or attack vector scenario and this is the stuff that the LMS pretty suck at. They they are not able to think as an attacker. So example here basically the wipe fuzzing flow is that uh the prompt is something like create flow that mints tokens to a random recipient check that only the owner can mint verify token minted event update token state balances and it pretty correctly generates this boiler plate code. Uh so here is the flow function. Uh there is the initialization of the random parameters.

uh it does the transaction but then here where is the actual like uh event handling and where is the updates of the local Python model here it kind of like makes mistakes so this is the part that still the auditors need to write themselves but we have kind of solved part of the problem that uh at least half of the code now can be uh wipe coded because the LMS understand the framework and by this approach we of course reduce the main pain point which is the development speed. So now we are much more efficient in writing the model. we are able to solve by this kind of like the updates for the protocols because the LM can do it and there's still pretty good safety

net which means when there is any hallucination or anything usually it means it fails which means it produces false positive finding which we can then debug and see that okay the logic implemented by LM was wrong and u the question is if LMS can do it all so not yet but this will be of course like kind of northstar to have like you know vibe fuzzing framework that would be fully autonomous. So back to the machines we see there are like three main limitations. So uh the workflow would be easy just the AI generates the test in wake framework executes that and auditor just reviews the results. But

the main problem number one is that uh what we do during the manual guided fuzzing is basically we read the documentation and rewrite the key mathematical formulas in Python which basically means we are rewriting the protocol. So for the LLM it would need basically to wipe fast wipe wipe code the whole protocol from documentation which usually is in web 3 like sucks the documentation. So that's the main problem that the LMS basically cannot reproduce the protocol based on the data that they were given because the data are not prompts for LMS.

Uh second problem is when I touched a little bit that when the test fails still still there needs to be someone who checks if either the test is written uh incorrect or if it's a bug. So this still kind of like this triage needs to be done by humans. And uh third problem still like human creativity is the best in finding the security narratives which means usually LLMs are trained on the data that were there you know but the tech vectors are evolving all new. So this is the key input that still at least for now needs to be done by humans. But if we solve these three questions we can have fully

automated AI fuzzing. So yeah that was uh that was my talk. Uh it was quite quick I see. So uh if there are any questions you have to ask me. [applause] Uh on one of your slides just now you said there's a potential for like uh so if AI makes the model then usually those bad tests are filtered out as false positives. What about when they're like not like it makes two mistakes that cancel each other out or something or like you said with the balances it reproduces the over underflow issue.

like the main problem is that the AI doesn't create the model because for for that we don't have the data such as the documentation and stuff like that or if it creates the model uh it creates the model from the solid code which is wrong because basically the idea here is that we are not affected by the solid code uh so we don't implement the possible bugs in Python so basically we have to look at it like uh uh implement the model without looking at the solici code which elements cannot do right now so basically this is the main problem in setting this workflow >> I mean like a human can also make the same mistake right which is reproduce the >> but the human can do such a things I don't know ask on a slack channel hey guys how does this work you know I'm

trying to figure out and this is the thing that uh we don't have in the in the AI workflow okay so thank you very much and see you soon [applause] thanks and um is Andy. Okay, perfect. Sorry. [clears throat] Perfect. So, our next speaker is Andy M.

Lee, founder and CEO of Memory, and he's going to talk about the current problem and solution of fuzzing. Okay. Thank you. >> Yeah. Yeah. Thank you. Thank you. >> Yep. >> Oh, I don't I don't know. Yeah. Yeah. Okay. Yeah. Cheers. Cheers. Yeah. Um so, um so basically like um it's really bad title. I know. Huh. It sounds like quite boring. So, the first part basically I'm going to talk about like um the problem of fussing. Like we talked about a lot of like problem of puff fussing. Then I would use a lot of like real world

example for instance like the balancer hack strategy and that like um to dive in why like we cannot cover those kind of uh those kind of exploit and then later on I would also like um using quite a lot of code snippet to actually like show what my proposal solution. Yeah to give a quick intro. So um back in time I was teaching at and uh teaching and researching in in economics actually and then I was doing like a microeconomics optimization base and then later on I moved to like machine learning research like back in like uh 2019 something around that and then doing like those kind of random forests and optimization again and then uh I worked for aises for a short while. I'm thinking about like um what kind of things stopping us to actually come into crypto and then it's actually here why

we are here security is the major robot for the crypto mass adoption. So I just like start the company and then to actually like trying to contribute um the the security space and then so this is like basically what I built on memorial to actually for value extraction. So first of all like we need to understand like what is value extraction my my my feel on the nature of exploit. So in the end it's actually two things the main two things one is like uh two step of optimization the first step is actually when we plug in a smart contract what kind of state changing function we should actually test and then we can actually form a sequence for instance like we have add collateral liquid we remove collateral and then given this sequence what kind of parameter of input so that's the second step of the continuous

optimization then in the end actually like combining these two functions and parameter then that will be calling value expression so our muv board is is the same thing intense solving it's also the same thing economic exploits is actually something the critical one that we should really solve it so um the two things that I I'll later on like talk about the jargon and those kind of things as well and yep and then we basically like all this function in the end we are actually changing the state I don't care about like uh we run 100 functions together as a sequence or we run 100 function one by one one by one change the state and then we add a function after to actually trigger the exploit so in the end is actually changing the state and change change in

value. So um I'll start giving like some motivation example that um why um it's actually feasible to actually using fussing to find exploits. First of all, like uh like actually back to last uh last month like we have the mean spell uh exploits and then 1.7 million exploits and then the core uh the core the core root cause is actually um when you run a weird action action ID. So it's like one of the function that you call is called um I think it's called cook. Yep. This is like I think like really a lot of people should visit the D5 headlabs like uh reproduction and then this is the code snippet from that and then when you form the uh the code and the coke function in a actions the action is a you're in array then if you

put it the first action as the borrow and then the second action is at sort of like empty zero so it's like a sort of invalid op code then we can actually bypass the in in solvent track so this is like the core critical root cause but you can see the reproduction That's it actually like the actual exploits they have like uh generate the full cost and then they also like swap the function back uh swap the swap the token back and then return the fresh loan those kind of things in fussing is actually something I call like dimensional reduction we can actually reduce those kind of things. So uh we talk about like approval and then like profit vacination swap and then and then the loop based exploits is also like uh something that we can actually reduce. So for the next phase is like I

give another example for uh I also found a a a another explore like uh in back in April that talk about live protocol that they leverage a sort of price manipulation by using the loop. So they do like for loop for like uh 50 53 time like buy and sell and then when you buy we push the price and when you sell they actually forgot to update the price and then they can they can actually uh gain the profit. But those kind of loop when we actually think about fasting we don't need to run 50 something times we can actually run or maybe or five time or even one or two times we push the price we get like 0.01 then actually we can sort of detect the exploits. So this is like making more feasible to actually think about the first thing. The next

things is actually like the the the the major news about like the balance exploits. Um the first part I was talking about the sequence that uh is reducible. The second part is actually uh we need to understand more about like the input parameter mutation. The second part of the optimization the so uh what's happened in the balancer is that like uh the core details is actually like they have like a upscale function that uh actually causing the rounding error. The entry function is actually the best swap and then the bash swap they go in several internal core and then like the internal core they the core things is actually like uh from the best swap one of the f contract they have the internal core internal function call and then one of the internal function call that will be talk about the external function call on swap and

then on swap they go for several internal function call in the bar in the pool contract and then they will trigger the upscale and then to trigger the rounding error. So um later on like when I talk about my framework uh well my solution is actually uh proposing a solution that how do we even we know upscale is the problem how do we get into this branch yeah and then I was talking about oh why uh why balance batch swap is really difficult so I'm talking about the difficulty so first of all like we actually understand a bit like about the input parameter so a lot of time we think about like the input parameter is actually continuous but uh a lot of complex type for instance like dynamic tupole and then dynamic array those kind of bite type and then we also need to know uh what kind of input

parameter we in this batch swap function is used for the external call later so it's like for instance like the uh I screenshot here like the the swap.pool pool id that particular bite 32 type is actually used in on swap later. Yeah. And then also like talk about like the external call dependency and then uh how do we actually know that the linkage between the caller function parameter to the call function parameter because we cannot mutate the callie function right so we have to mutate the the the entry function. So basically that's is like the motivation example. Then uh when I when we talk about fussing we need to actually understand several jargon that I will keep using. So first of all like is actually think about uh the common framework will be when we start a smart

uh first a smart contract we think about oh this function we need to start then what kind of parameter of input so the argument initialization and then like we also need to think about how do we generate the sequence what kind of test case that we need to do and then if given this given this parameter of input we how how do we mutate for the next one so this is like academic paper that I I I also read I find it like really good for learning fussing and then the s mutation that will be and then the feedback mechanism is thinking about like for for instance like code coverage or like coverage based or this metrics kind what kind of metrics that we can use to guide for the next mutation. So u this time I deposit $10 next time do I deposit $9 or $11 which direction I

should go. So this is like basically the the the seat mutation and the fifth band mechanism and then of course like uh we talk about the but oracle a lot of people confused about like the the oric price oracle in in the space but it's called like the butt oracle it's like what kind of things we classify as the butt and then the scheduling those kind of things. Today I will basically focusing on the on the sequence generation and then mutation part. So basically the two-step optimization I talk about. Yep. So uh I was talking about like what kind of problem. So it's we're still in the first path and then um so those kind of common problem that people would expect and then we think about like a state exposion. So it's like we have so many like for for for a smart contract we have so many different

multiple function and we can actually combine this and then we uh combine this together to actually concern or the state exposion as well and then that could be like also looping between like uh between the functions as well. So this is like the state exposion and then we also having like within uh within protocol multicontract uh dependency. So you can think of like each smart contract address is a system. Then the major problem of the traditional software engine uh software testing is actually we targeting one single system for instance the gaming but like in smart contract we actually have like multiple address for one single protocol. Then how do we actually cover the external core and multi system and then also like the proxy contract that we have the s storage in the proxy contract the the logic is in the

implementation those kind of things is actually also like quite increase the difficulty then of course like the dynamic external core that those kind of price oracle manipulation then how do we know that this protocol is actually integrate with other for instance like the uni4 actually having the hook you can actually link to so many different protocol then this is another like difficulty then current approach for actually solving this um sequence generation. How do we actually form a sequence? The first one will be thinking about the Rick and Y relationship. Then you can think of like Rick and Y is like deposit like and withdraw. How like we deposit and then that will be changing uh as store the storage slot one of the storage slot. Then how do we uh then we can know that the next function we actually use is actually as low that

particular storage slot. Then we can actually combine this fun uh function together as a sequence. And then the next thing is actually we talk about like customarium. can actually leverage the leverage the auditor knowledge to actually like really specify the test case that we want to do and then the next thing is actually uh thinking about like those kind of state based snapshot which is like the ATS and then uh smartshot they also do it in in this way then the next challenge I I'll go yeah sorry I have yeah I need to go faster as well and then the next challenge will be thinking about like uh you see the best swap is really difficult and then how do we actually do the parameter generation what kind of difficulty that we actually have. So the first things is actually API type uh we use AI type uh mutation a

lot and then really unique address string those kind of things is something that mutation the traditional mutation we cannot do and then the next things is actually dynamic array. So when we actually think of dynamic array uh batch swap they have like dynamic array dynamic tupole dynamic address then those kind of things is actually increasing the possibility of the argument as well uh argument uh argument mutation that will be really increased a lot and then the format is actually like uh to put the dynamic array data that is quite complex as well and then also like the dynamic array and then we also have having those kind of core data as an input. So uh this is one of the one of the example moon hacker actually last year yeah got hacked and then by like

300 around 300k and then you can see that like what they do they actually use a core data to as an input and then later on is actually decoded and to the exploit basically like when the uh attacker put the address after decode as the malicious address then you can actually bypass some validation and then you can take the money out. So the the difficulty is actually craft a call data that actually bypass it and later on I will talk about the solution into it as well and then compress data type call data that will be uh used it for the later on uh call function or swap as well. Yep. And then current approach for the Yep. Um so we can actually think about like what kind of current approach and the classic one is something called like uh Harford mutator with the lip AFL

uh library. a lot of like um fer actually using it and then they have like so many uh different mutator bit those kind of like flip zero to one and then one to zero and then those kind of things by ABI and then the next phase is will be thinking about distance matrix you can think of like I require the balance greater than 10 and then now my my balance is one then I know that I need to increase my balance to like 10 in order to bypass some uh bypass a branch and then later on that also like leveraging some automization algorithm to actually mutate for the input parameter. Yep. I think I'm going to the second part. Yep. So, um my my proposal solution that will be like thinking about a three- layer approach. The first approach is actually leveraging some LM

into guiding the fusser and then that will be having four part of it and then later on I will talk about like uh uh the the state based fusser that um that that that that I I'm building and then like the the the EVM execution actually we can actually parallelly uh ex uh execute on the on the GPU. So the first part for the LM we uh we actually have four part the T analysis external core trace and then compressed data generation and then dynamic runtime information those kind of mechanism. The first thing is actually you can think of um a lot of people actually doing it as a like uh a you can think of static analyzer version of the LM. So replace a sliffer. can think it this way and how do we actually having uh having having uh like we can actually have different

technique to do it and then the core things to actually link the static analyzer to the fussing is actually what I think about if the LM identified line 177 is the vulnerability we need to get into the upscale then how do we know that is actually uh how do we actually get into the upscale and then one of the mini trick I try is actually that we can on the source code we can actually uh add the assembly code or something like ox777 777 and then we know that on the control for graph here is the particular basic block we need to get in. So we can actually ident identify what basic block we actually get in to trigger the potential vulnerability. So the next phase is actually think about um the for the LM to guide for the first thing is actually uh I was talking about the best

W and then how do we know that what kind of best war parameter I can mutate on the on the later on inner on swap function. So on what on swap function they are having request but how do we know that we cannot change requests how do we know that which parameter I should change in the upper function to change the request. So this is like the LM understand the source code can actually identify uh which one is it. So uh the approach we do is actually you can think of like given a smart contract we find all the all the caller function having external call. The second stage is that give uh we know that uh the caller function. So for instance like uh for this is a unis swap uh pool manager contract uh we have the swap function in the pool manager contract what kind of

external call function they are having the callie function of the swap function and then we have like before swap and then the third part is that like what kind of parameter of input that we can actually trigger the address to for the before swap. So that's the third part and then the fourth part will be thinking about given the before swap uh par parameter of input then what is the suspected uh um valid input input for the call function and then we can actually ask the LM to generate it and then we the next step is actually map the callie and caller argument together to generate a valid input. So this is something that I think we can do. And then the next part is actually thinking about complex data uh generation is thinking about the I was talking about

the moon hacker having like a core data as an argument. The approach that I do is actually think about you can think of this core data is decoded into three things. We can actually think about another logic of oh that means I can use these three things to encode it to a call data and put it in the function. So this is like uh one of the things that we can actually generate ask the LM to generate a script to for a function that having for instance like operation m token and then a mind to supply or redeem to com to to generate a call data to yeah to actually like start this kind of compressed data type. The last thing is actually like if you think about um the the the revert message like human read it when we test it we know there's

like some reverse message for instance like this case is like we have like require some uh verify this is like one of the exploit that I I I was checking and then like uh oh it's not eligible then how do we for human we can actually know oh it's not eligible but in the fing process like because it's so fast we can actually when when we read the rever message in the runtime and then we can actually ask the LM to guide it uh what kind of requirement we need and then the proposed uh argument that of input. So this is something that we can do. So the second layer that we'll be thinking about the state base the three phase uh CFG guy uh first thing and then the state pool and then some sort of like uh state diversity concept. This is like quite uh new in the space. So feel

free to uh later on challenge me on all this idea as well as always. And so so the first part is actually think about the question we are asking is how do we get into the particular branch we know upscale this particular branch but how do we get into it. So the first thing is actually that we need to understand for the CFG which basic block is in for that particular branch and then the next things is that when we actually bypass the path we uh into that basic block we have different like jump I condition or like comparison op code and in the comparison off you can see that they are taking storage what kind of storage they are taking then we know that by this comparison code and then jump I we know that we need to mutate the storage and or argument and then in this case this

is the storage we need to mutate and then yeah and then the when we observe the argument of storage we can actually see the the distant metrics that I I I I talk about then the major challenge of this problem is that a lot of things like uh for the CFG generation like uh any CFG expert also like feel free to to discuss with me as well and then so that will be like uh infinite loop problem when we generate CFG one function access together then they keep accessing together that will be causing CFG problem and then for loop that will be like a while loop. How do we know that like CFG generation keep generating and then the external call that will be difficult because like in the external core we see there will be some in here that will be a call op code and then the

external call we don't know uh inside that uh like what kind of further logic that we have and then the memory usage as well some sort of jump I would use the memory to to to help for the uh to help for the comparison to bypass the condition but we can actually do memory tracing yet memory tracing to actually find find out like what kind of argument or storage that we do and then dynamic storage operation those kind of things are uh using kit kat as the as the memory to find the uh me use the key cap for a memory to find the storage location and use the storage to find the storage value. So those kind of things is something difficulty that we can encounter. The next part is actually think about we know that uh we need to

mutate the state but what kind of state we need to fetch. So uh you can think of like uh first of all we store the interesting state similar like ET also doing it and then um like some other fer they also do it it and if there's like state change and then that in that sense we need to add to something called state pool a a server that actually storing all the state and the next things is actually like we fed uh we see the as low slo op code to know that what kind of state we need to take the another is something that state compounding is thinking about like if I want to get into Sorry. [laughter] Uh if I want to get into a particular branch, we know that the whole path then we know that a set of storage that we need to get in then

but we also have like different state that we generate with the with the call chain. Then we we can actually combine this different state together by re-executing the the the the call chain in order to uh generate more of uh more more diverse state. Yeah. And then the next things is actually think about uh diversity concept. So is that um a lot of things we need to manipulate the state even I get into upscale how do we trigger the particular vulnerability. You can think of this is like two two things constraint optimization or like uh and then like constraint generation when we get into the path we can actually generate different constraint some other uh some other fer they actually do it but like they assume the linearity problem. So we we can only like keep uh doing like basically

fussing and then when we bypass it we can actually record the value and those kind of things can be used it to help for the constraint. The next thing is actually think about um the given this constraint how do we actually extend the state base and then pretty much like it's running an optimization problem that uh we can actually do. So the third layer is actually thinking about like the yeah the the GPU uh so GPU execution the high level idea. So basically you can think of like when we put in a smart contract and then that will be like a a bite we trans or transform it into a basically GPU paralyzer code and then execute on the GPU. You can see like uh one of the mu first like one of the academic paper they do. Yeah.

So this is basically my solution and there was some further discussion then I mean I time itself and then feel free to come to me and then there will be like a lot of different question that we actually uh can can can talk about like and yeah I mean time is up and then reference list and just come and talk to me. [laughter] Yeah, sorry for speaking that fast. Thank you. [applause and cheering] >> Yeah, the the time is good. Yeah. Yeah.

>> Hello. Thank you for the talk. It was pretty good. I wanted to ask you when you're thinking about fasting and you know sometimes based on resources because I read we we still do not have quantum fing and we have like infinite paths to what are some key points or some key ideas you use to guide the fast test? you know maybe bound certain values that you that you think or path that would lead to certain bugs. What are some how do you say key techniques you know that you think

about like okay I think like if I take the zero value like it's probably you have set to zero set to the upper limit or you know try to get it to the edges probably what are some techniques or >> I think the core technique I will think about I was talking about the distance metrics when we look at the compression op code. So you the op code they will have like greater than less than or storage greater than something and in the source code we write it balance greater than something then we know that that compression of code guiding us that if we even we start from a million then the compressor off code is actually telling us we just greater than one and then we know that the distance is actually from million to one then we

know we can actually either increase or decrease we decrease it and see the distance whether it's closer then if we is it closer then we keep going this direction. So this is like some core technique that I think uh that guiding guiding the fusser to to do it. Yeah, it's like sorry if I keep talking. It's like something used in finance that it's like the less amount of tries like that you you you see okay I have free tries to determine something like and you go like I don't know in a 100 store floor that you would test the nine the 29 and something like that. It's yeah I get the idea. Sorry then I will ask you. No worries.

>> Yeah. Yeah. Yeah. I think that's good. any any other question feel free. Yep. Thank you very much. I mean feel free to actually talk to me and yeah I mean uh like the whole presentation is really for facilitating discussion and that's the purpose of why we actually hold DSS maybe. [laughter] Yeah. Thank you. [applause] >> Thanks again. And now we have a lunch break. So a lunch break. So if you want to talk to the speaker it's a perfect time.

Okay. Hello. One, two, three. Everyone can hear me. Okay. Everyone has had lunch and we're good. Okay. That's very good to hear. Well, welcome to the afternoon session. My name is Andy Paladino. I work at Aztec. I'll be the host for this session on math and zero knowledge. And we're getting started with Jeffrey Scholes. Yep. Did I pronounce it correctly? >> I'm sorry. >> Did I pronounce your name correctly? >> Yes, that's right. >> Okay. Awesome. on understanding math heavy code. The idea of the talk will be basically to stop being afraid on math code and and and have the understandings needed in order to actually be able to review and audit and follow that code and in particular Jeffrey is going to

pick on a piece of code from unisop v3 for that. Um Jeffrey. >> All right. Thank you so much. >> Sure. >> Okay. So today we're going to be reading uh this code. Um, all right, cool. Based on a few reactions, it sounds like we're going to have fun. Um, okay. Now, for let me just say that obviously every math uh library is different. The whole point of this talk is just to talk about how can we turn a big scary problem like this into something that's manageable because every big problem can be solved by making it smaller. So the whole point of this talk is just to talk about strategies for how to look at a big math routine and say how can I figure this out bit by bit versus just reading the

code and feeling overwhelmed. Uh so first where do these math heavy functions come from. Well most of the time when you encounter a heavy math uh library like this it's because there's some gap in solidity's capabilities that the authors were trying to fill in. So, for example, if you use Rust, you can just do um F-32 log 2 and then you have your logarithm right there and it'll give you a float back. But you don't get that in solidity. Or if you try to raise a number to a fractional power, you can't do that. Uh so that is where these things tend to come from. Uh okay, so first of all, uh I'm going to give two seemingly obvious pieces of advice, but as I've helped people walk through these things, it actually doesn't seem

that obvious. and then I'll get into the more uh intricate strategies. All right. So, um the first thing when looking at a math code is you don't really want to read it like a regular code, right? Okay, I'm just trying as as these lines execute, this is how the state changes and one thing happens after another. It's much easier to read a codebase if you already know what it's trying to do. And math is not an exception to that. you want to know the formula that it's trying to implement and what size of numbers that it's expecting to receive as inputs and give back as outputs. So, uh do I have that here? No. But so let's let's go back to here. What is this even trying to do in the first place? Well, luckily unlike a

lot of other math routines, they give the formula on top over there. We're computing uh 1.001 raised to the tick square root multiplied by 2 96. All right. So why is it multiplied by 2 to the 96? Well, because you don't have fractions in solidity, right? So what do we do in order to capture the value of the fractions? We use what's called scaling factors. Kind of like how ether everything happens in multiples of 10 18, right? One ether is 10 18 and half an ether is 0.5* 10 18, which is still encodable as an integer. So since this square root of 1.001 001 raised to an integer is going to be not an integer most likely then uh we need a scaling factor in order to make sure that the decimals don't disappear. Okay, I I'm

not gonna if if if you don't already know how unis swap v3 works, honestly, don't worry about it. It's not actually relevant here. We just want to compute this formula. And trust me, bro, it's important. But if you already know, this won't surprise you. Okay, so that's understanding the intent, which means we looked at the formula. And the other thing I would say is, okay, we looked at something that was dealing with square roots, right, and fractional exponents. Chances are you haven't worked with algebra in a long time, unless this is something you deal with on a daily basis. So, it's good to bring back to the top of your mind, hey, what are the rules of dealing with exponents? We're actually going to see that today. Uh what are the rules of dealing with logarithms if that's what your codebase happens to be doing? Because uh without

that fresh in your memory, it's going to be a little bit hard to um uh follow it. It just makes your life harder. Obviously, the other thing I would say is uh fixed point numbers, if you're not already familiar with them, that's probably the first thing I would learn if you're diving into the world of uh more intricate DeFi mathematics. So, the I guess the fixed point number is we multiply all of our numbers by 10 to the 18 in order to capture the decimal portion. Uh another common thing is we don't multiply it by 10 the 18, but we multiply it by some power of two. Uh like 2 to the 96 is what we saw here. Now, why might we do that? Well, because multiplying and dividing by a power of two can be done with bit shifting, which is more gas efficient. So uh when you

use the power of two that will tend to be called a Q number but a Q number and a fixed point number are the same thing. Okay let's talk about uh intelligent sub goals. The first one is okay this all of this scary stuff over here is probably not where we should start because we we look at it then there's there's going to be spirals inside of our eyes. Uh but if we look inside of the purple boxes here it's actually really not that hard to tell what's going on. Right? So they even have a nice variable. It's saying this is an absolute value. And honestly, if you look at that, it's not hard to tell that that is in fact an absolute value, right? If it's negative, multiplied by negative 1, otherwise return the original one. Um, and then obviously this is some security check to

make sure that's in range. No problem there. This one might be a little bit interesting. Um, but note that when we have the ratio, we we're taking the reciprocal of it. We had the ratio and then now it's in the denominator. So we're taking some kind of an inverse. Okay. Now why are we why are we not doing one over ratio? Well, we we cannot do one over ratio because ratio is going to be bigger than one. And if you do one over uh something bigger than one in solidity, you get zero back because it rounds down, right? So um this is accounting for the scaling factor. But over here we can say if the tick is bigger than zero, then we're going to compute one over the tick. Okay? So that might mean we have to be conscientious that there's a reciprocal going on

somewhere. And over here the the comments are actually telling us what this code does. But remember how I talked about it you can uh bit shift by 32 which is more gas efficient. Well that's what they're doing. And they say we go from a 128 to a 96. Well that just means uh we went from fixoint numbers that have a scaling factor of 2 to the uh 128 to a scaling factor of 2 to the 96. And you can tell that because it's uh right shifting. So it's reducing the size of it. Uh what does that tell us?

Okay, well now we know that if this is transforming a Q128 to a 96, these must all be uh fixed point numbers with a scaling factor of 128, which kind of makes sense. There's these 128s floating around there. Okay. Uh so that that gives us an important clue. At least we know the scale of the numbers that we're dealing with. The other thing that we can look for, I didn't actually call this a strategy here, is that it's probably very hard to detect the pattern in these big numbers over here, but um it's a little bit more obvious what's going on inside of these purple boxes.

Anyone recognize what's going on there? Yeah. So, they're powers of two, right, in hexadimal. So, um that's interesting. All right. So, we're going to trigger something based on a power of two condition. All right. Now, how does this relate to square roots and 1.01 raised to the 96 and all this stuff? Okay. Well, we don't know. But the nice thing is we're making tangible progress. We figured out bits and pieces of the code. And hopefully we get a connection as time goes by. Okay. Because this uh if ABS tick and 0x2 or ABS tick and 0x1, okay, that keeps repeating, it's probably worth figuring out what that does. Well, this is just a bit manipulation trick. It's saying if

the first bit the least significant bit in the number is one and you end it with one is going to be one and one is not equal to zero. So that means it's going to return true. What this means is that uh this is just detecting if a bit is one inside of the number. So this detects if the first bit is one. This detects if the second bit is one. This detects if the third bit is one because the binary representation of four is 1 0 0. the binary representation of eight is 1 0 0 0 um and so forth and so on.

All right. So abs tick and 0x2 returns uh zeros and one at the second bit if it's one. So if it's not equal zero that will trigger. Okay. So we know we're doing something with bits. We know we're doing something with scaling factors. We know there's a reciprocal and some absolute value. But that still doesn't tell us how we're computing the square roots. Okay. Um, now one way to kind of get your foot in the door and figure out, hey, I need to at least get a sense of what's going on here, even though I understand little itty bitty pieces of it, is uh, let's test out the easy cases. Like, we know that the square root of 0 is supposed to be zero, for example, right? We also know we're not exactly computing the

square root of 0. We're computing root of 1.001 raised to the tick multiplied by 2 96. anything raised to the zero power is one which we would know because we brushed up on our algebra before studying this, right? Um but the square root so u one some number raised to zero is one and then the square root of one is still one. So we know that this whole thing is supposed to output 2 to the 96 at the end if this formula is being enter uh implemented correctly. So we know the correct answer is now we just have to figure out how does how does the code go about accomplishing getting that correct answer. Well, since we know one is supposed to be uh the output or 2 to the 96, which is the scaling factor of one is supposed to be the output. Well,

luckily we do in fact see uh one over there, right? That's one. Uh I'm not going to count the zeros for you, but you will actually see that that's 1* 28, but it'd be very boring if I counted, but you could plug it into Python, get the string length, do it that way because counting it by hand is a bit painful, right? Okay. So, uh and under what conditions do we get our answer to become one? Well, that's when the um that's when that's when none of the bits are set, right? So, here we get one and here we get um this is not going to trigger because tick zero is not greater than zero. So, all we're going to do is just take this number and then shift it to the right by 32 bits. Okay, so that's how we get our correct answer.

All right, that was easy. Now, rather than making a Yeah. >> Uh wait, sorry. when this is false. Yeah. >> So the last bit is not is is zero. >> Okay. So um when abs okay let's say abs tick is all zero right. So zero um and some non-zero thing is going to be zero and zero is not equal to zero. So it's going to trigger the false condition. So that's when the tick is zero. Now, because we know, we kind of want to avoid this guy over here because he's going to complicate our life. So, we say, hey, if I I don't want to be thinking in terms of reciprocals. It

looks like this is only triggered if we're dealing with uh non-zero ticks that are one or higher, right? So, what can we do to um make our life easier? Well, let's test out the negative one tick because negative 1 is not going to trigger that. We already know what's negative 1 going to do over here. Well, abs tick is just going to be one. Uh, it's only going to trigger this branch over here. And then we know down here it's just going to shift it right by 32 bits to correct for the scaling factors. Okay. Um, now let's think, well, what should the answer be? Well, according to our formula, 1.001 raised to the -1 root of that multiply that by 2 to the 96. We can do that in Python or rather 2 to the

128 because we know we're dealing with higher scaling factors right now. and it matches at least up until we get until later. So the thing is Python uh has limited precision unless you force it to be higher. So you can use the decimal library in Python if you wanted to force it to be accurate. Uh but I just want to show this to you because you know when you first do it in Python you're like is my math wrong or no it's Python's wrong. Okay these are a lot of decimals. Okay but now we now we know where these numbers are coming from. So reverse engineering these big constants is a very nice sub goal to have because you get um you understand what the logic behind what the developer was thinking and it's manageable even though we don't understand how the entire codebase works

yet. We at least got into their thought process for where they where they generated these large constants just by knowing hey this is what the correct answer is supposed to be. Here's an intermediate state and I only have one missing piece of information so I can triangulate it. So tick two the binary representation of two is one zero. So that's going to trigger the second if statement and we can compare what we expect the outcome to be versus what we actually have in the code. And aside from the rounding errors, we can see we actually get the answer that we were expecting. All right. Well, that's nice if we're dealing with uh ticks that only trigger one if statement. But what if there's uh more than one tick? Uh but first of all, before I do that, let's just talk about all these right shifts by 128 that are

happening. All right. if um ratio if you trigger multiple ticks it's going to keep multiplying these big numbers together and you're going to very rapidly hit overflow as we multiply right so what it's doing is saying hey these numbers are scaled up by 2 to the 128 when you multiply two numbers together that are scaled up by 2 to the 128 now you're scaled up by 2 to the 256 so you need to divide by uh 2 to the 128 in order to bring your scaling back down and that's what right shifting by 128 does so it's the same as dividing by 2 to the 128 eight.

All right. Um, okay. So, let's uh figure out how does computing the tick for negative3 work? Well, first of all, what's the binary representation of three? Very good. One one. Yeah. Right. So, we know both of these if statements are going to trigger, right? both the the one that checks if the first uh bit is set and the one that checks if the second bit is set which means ratio is going to be set to this big constant over here and then ratio is going to be multiplied again by this big constant over here and then scaled back down. All right, so this now what's the logic behind multiplying these constants together? Well, it's probably not obvious at this point in time, but we know what it should output, right? Because we're supposed to get

1.001 01 raised to the -3 roo<unk> of that multiplied by 2 96 and we can check the expectation versus the outcome. We multiply those two constants together and compare to actually computing the tick for neg3 and we see that aside from the rounding errors, we get what we expect. So we know that this code if if if it's dealing with a number that's not a power of two, it's somehow able to take other powers of two and multiply them together to produce the answer that we're looking for. All right. So, this is actually what's going on. Again, we need to bring algebra back to the surface because uh when you have this kind of a I I don't when you have this arrangement of numbers, you can actually draw you can draw a square root over both of these guys and it looks

like the one on the right and you actually skip some steps here. Sorry. So, when you have two square roots, you can multiply them together and bring them under one square root. And then when you multiply two numbers of the same base raised to different exponents, then you can add the exponents together. Okay? So that's what's going on. 1 plus -2 is -3. And we brought them all under the same square root. Maybe a nicer way of thinking about it is square roots are a number raised to the 1/2. So you could think of it as umgative - 1/2 plusgative -2 halves. So um yeah, that's that. All right, I'm actually on the last slide now. So what is the codebase doing? What's the general pattern? Well, it's looking hey if we if if we have a number say 14,

it's going to have a certain binary representation, right? In this case, um 1111. Okay. And if since our code is just ratio time ratio time ratio time ratio, if a bit is set, then we're just multiplying these premputed constants together. So 1.001 001 to the4 can be represented as 1.01 raised to the -2 * 1.01 raised to4* 1.01 raised to the8. All right. So that algorithm actually has a name which I found uh one of my my colleagues when I explained this to him

he's like oh yeah that's the square and multiply algorithm. Like why did you why didn't you say that earlier? I could have just looked that up. So um if you're I mean one obvious thing you can do that I didn't mention here is just shove the code into the AI and tell you what answer it gives you right um I've actually used this as a benchmark for sensing how smart the models are becoming because this is something that they will tend to hallucinate on but a more rather than asking it to explain it to you which it's generally going to do poorly on at least in recent tests is say hey what algorithm do you think this is implementing and then I'm going to look that algorithm up and then I'm going to study that algorithm and then apply apply it back to the code. Now,

you want to ask several different AIs because they might give you some variety in their answers, right? Uh but um that can be a helpful starting point. So, the algorithm that's being implemented here is actually has an official name called the square and multiply algorithm. Uh but using this technique, I was able to figure out what it was doing before I knew that algorithm existed. So, just to summarize, when you're dealing with math, obviously start with what's it trying to do. Don't read it line by line by line. Write out the math formula what it's trying to do. Second of all, uh any relevant math, whether you're dealing with logarithms or exponents, bring that back to your head because we had to deal with raising things to the zero, bringing things under the same square root and things like that. That would we would not have been able to do that in

18 minutes if that was not fresh off the top of our head. And then the second thing is pick intelligent sub goals. So that usually means picking code paths that are going to trigger as few if statements as possible. And then moving on to figuring out what are these large constants are and am I able to figure it out while also using the decimal library in Python to not get hit by rounding issues when I'm making estimates. All right. Thank you. [applause] >> Thank you, Jeffrey. Uh, we're almost on time. Maybe we can have time for one question if there's one question from the audience.

Anyone? Okay. Um anyway, if you want to follow up, I encourage you to check uh Jeffrey, the founder of Rare Skills, which is a web3 technical education platform where they deal with precisely this kind of stuff, both math and zero knowledge um heavy content. So encourage you to check it out to learn more. By the way, I had flashbacks on Carmax code on, you know, the inverse square root in the Doom source code. I had like the exact same feeling when you were describing this like reverse engineering how they're using like something very very platform specific in order to derive something that's very very math heavy. Uh I love the talk. Thank you very much.

>> Thank you. >> Okay. Awesome. Please round of applause. [applause] Okay. Uh next up we have uh Janice Deusher. Uh I'm pretty sure I pronounced it wrong. I'm very very sorry. Um, Janice is a security engineer from chain security who works on smart contract audits. And well, we have just seen how to model different math constructs using EVM primitives. And now Janice is going to walk us through how to bound the errors that come from those constructs from those from the translation. And in particular, uh, Yanice is going to focus on ERC 4626, uh, volts. So, um, Janice,

whenever you're ready, um, guys, please settle, sit down, and please silence. Okay? >> All good on your ends. >> Okay. Now, it's >> okay. All yours. >> Okay. So, um, I'm going to speak about u rounding errors. And um especially I'm going to speak about how to find the the the bounds like how bad can we round um can you round down or up. So yes.

So so uh oh yeah first of all my name is Jianis. I'm security engineer at chain security. um I audited a few projects but anyway today we're going to disc so first to discuss rounding errors we're first going to discuss um some common patterns like what's happening what's going to be the limit what where is it going where is it going then we're going to discuss the volture pattern but we can see in 4626 uh volts and then I'm going to show how to prove that we cannot uh be more far off uh than expected and to do this we're going to use a Z3 three which we're also going to see what this is. Um so first why why do we actually care about rounding errors? Uh well for me I

care because it uh happens on all EVM chains. Um and uh where where on EVM chains we can mostly only see integer math uh natively and this always means that we are rounding down um and um well this also is um often quite hard to uh guess. You can see some formulas, you see some math as you saw previously, but it's hard to say like, oh, we're going to round down, but then we multiply, then we do something else, then stuff happens. And we actually don't know um how far we're going to be because when we think, we always think this is going to happen in real values.

So when we when we imagine like three over two, we can easily imagine 1.5 or we can imagine some stuff, but it's not what's actually going to happen. So if later you multiply, then you're actually really far off. So we're going to see how we can a bit uh understand things. um that happen on chain and also um usually this kind of issue they wouldn't be flagged by any tools or even I think AI is quite bad at finding these type of issues so it's good if we can reason a bit about those and oh yeah and last reason uh it happens quite often that there is a lot of money which is uh leaked by this um tiny rounding errors so um yeah so what we're going to see is

like this kind patterns. So simple of some at the beginning somewhat simple expressions. Um and the the goal is going to be trying to figure out how far can we be from the real value. So we're going to like see this value in solidity where when we divide like for example if we do like a is 10 and then we divide by three well we should get 3.33 something but instead we get just three and then we multiply. So then we're again like uh way way further away depending on how big C is. Um, so this is what we're going to try to assess the difference between those two.

Um, and the first one we're going to be looking at is the most basic one we are going to see today. And we're going to ramp up the complexity. So if we have a time time a divided by b, uh, then you probably all know that um, the further we can be away is almost one. Like the worst case we can have is we were trying to reach maybe 3.99999 something. Well, we'll get only three. So the further we can be away is um is is three. Um which is sometimes quite bad, sometimes quite good. But this we can easily reason about. We know it's going to truncate just the the fractional part of the number. Um now when we have like the expression we saw before. Um this one maybe you also know how it it works. Um in solidity if you

just write this code of course it's going to be first a divided by b and then the times c comes later. So as we said before the the a divided by b we can be at most we can have an error of uh of of one. So then we multiply by c um and this error also gets multiplicated. So we can be at most um c away from the real value the the the value that we have in mind that we expect. Um so for example uh if we were supposed to get 3.99999 something then imagine C is is um C is four. Well, we expect to get like something like 12, but instead we will get just nine. So then we get uh a bit uh further away. So basically anytime you see like a

division um be careful because you might want to actually maybe do the multiplication before instead and uh like reorder the operations to get more precision. Uh but you also have to be careful about overflows and stuff. So there is things. Now imagine we have this and we had D. Um um we could like try to guess if it does anything. Um it actually doesn't. So like if we add stuff and everything, we don't actually change there is it's not going to amplify the rounding error. It's just going to shift it a bit. But it's really multiplication and division we should be uh careful about uh in this rounding errors. So now one which is a bit more complex um and uh

And on on this one, I'm going to spend a bit more time uh because people usually guess actually the wrong answer for this one. Um it's maybe not an expression we see every day. Uh we're going to see some expression that we see a bit more later. But so basically um in this one we have a over b and then we have something a bit similar to before where we had a over b * c but now instead of the time c we have time c over d. And uh in this case we have C is smaller than D. So we cannot really amplify the error as before because before we had C uh which could be big and then we really amplify the error in this one. Um C over

D is simply smaller than one. So you could guess um you could guess it's not going to amplify the error at all. And uh also there is no like issue with the parenthesis. We're going to do a divided by b. Then we do all this times c and then we divide everything by d. Otherwise c * d would c divided by d would already be zero. And then uh this is all zero. Right? So there is no brackets error. Um and um interestingly so then most people say this this should actually round um down but we're going to be at most one off because we cannot amplify. we have an error of one and then we multiply by something smaller than one. So we just don't amplify the

R. Well, actually turns out we can actually be two um two ways off. And this we can see um in this example. So in this example we have like uh a which is five and we divide by three and we get one. Then we multiply by uh c which is two and we get two. And then we divide by d with which is three and we get zero. Uh so this is actually a bit more uh further away than it's like further it's more than one off from what we uh expected. It's actually 1.1111 right. Uh so we we can actually be really further away than what we expect.

Um yeah so this is the kind of uh things we should worry about when we uh check the math in a smart contract uh because it goes a bit against our intuitions sometimes and this is also why later I will show how we can prove this kind of a formula. Um next we have the case where C is greater than D. Uh so in that case we a bit come back closer to uh to what we have we had with just time C because now C is greater than D. So we can again amplify the so it's good to think about like where we are in the like if we can figure out how big the numbers are going to be relative to each other. It can

help us actually figure out how far the entire formula is going to be from from the real valued formula. Um yes and then it turns out that the maximum error that you can get is ceiling the C over D + one which you can somewhat maybe uh it's a bit similar to what we had before uh right times C. So this is the ceiling of C over D and then the plus one also comes from the fact that we could have uh two ways of error in the previous formula. Um yes. So now what I want to talk about quickly is because for now we've been talking only about absolute error. So we are one way off, two ways off, C ways off. So we can

be we can be like a certain number of units of but what's actually interesting also is the how far we can be like in terms of percentage. So like for example if we have a correct result like the real value is eight but we have a computed result of six then the then the absolute error is is two right the difference between the two but if we have like a if we speak in terms of relative error we have like maybe eight and six and then like the the the the difference is like we're off by 25% compared to where we should be. So sometimes we do actually care about one way. We cannot be one way off or we want to do something if we're one way off.

And sometimes we don't care if we are less than 1% off. Maybe 1% off is fine. Uh maybe maybe not. Um and now I want to talk about this formula that we often see. Um and this is the formula which comes from uh the 4626 volt from open zeppelin. So we have like this formula to convert from share to asset. And basically it boils down back to this uh formula. And this formula we're actually going to compare this time because if we were to compare it to the real valued formula, right, we're back to the position a * b divided by c. And this is not really interesting. So we're actually going to compare this formula with the plus one to the a * b / c without the plus one. So what

does rounding does do for us when we don't have the plus one? Um so the goal is going to be to compare the real value target of a * b divided by c uh compared to uh the open zeppelin uh formula with integer. So what we would have onchain against what we would have if we if if we just think of a 4626 volt we usually have in mind this simple formula of a * b divided by c we have a share of the vault that's what we own and that's it. But that's not actually what's happening on chain and it's actually quite uh important to understand this kind of formula and how far can we get off from what we expect.

Um and so the first question I want to ask is um like what is the maximum possible value of the difference? So the absolute error compared to those two formula and of course it's going to be quite big in absolute like if you have 256 bits of integer the the difference can be quite big. So um so I'm going to present like a small uh difference. This is actually the biggest that you can get um with uh a b and c being smaller than a thousand. So it's like we have number smaller than a th00and and we already have an absolute error of uh 512.

So, so for example, if you take A being 512, B3 C1, this might not be numbers that you see every day in a vault, but this is what you can have. Um, then the real value is going to be um 1536 and the open Zeppelin formula gives us,024. So, that's a difference of 512. So, if you just think I have a vault, I have a * b divided by c, you might be far off. So, it's it's actually quite important. And if you think about relative error bounds, it's even worse because um you can actually be 100% off if you take small numbers. Of course, because if you have a being one, b being

one, and c being four, um the real value is 1/4, right? We just have one * 1 divided by four, it's 1/4. The open formula is going to give you zero because you do 1* four and then you divide 1* 1 and then you divide by four, then you get zero. It's going to round down, right? So you can be 100% off for small number and you can be really far for for big numbers. Um and now the question is those two we actually round down right because we divide so we round down. This is what you initially think and um the question is are we correct like the real value was a,500 and we go to just a thousand. This one was supposed to be 1/4 we go to zero so we

round down. But is it always the case? Can we go higher? We have we have a division where we round down but we do have some plus ones. So can we go higher than the real value and the answer is actually yes you can go higher. So this is a bit unexpected when you think about uh we just run down but no actually we have plus ones. So for example you take a being the numbers are a bit less nice. So uh but yeah you can verify the math right? If you take a being 189, b1 c20, the real value you should get is 9.45 and the open zipin version gives you 18. So this is actually nearly twice as high. It's it's really far from what you would expect.

Um now now now uh what I want to show is quickly how we can prove uh those simple formula like prove that um we cannot reach a difference of three or we cannot reach a difference of d we cannot be that far from the real value and to do this we're going to use a z3 which is an SMT solver. So this is basically um a tool which allows us either to find a counter example if there is one or to say there is no uh counter example which exists. So we will say SAT for satisfiable or unsat um and uh yes this is uh basically like fuzzing where you would um try to find a counter example but in this case

uh we know if we cannot find one we know that there is no uh counter example. So we know this cannot be satisfied. So the so what it's going to look like is like a small piece of code like this. Actually this is all the code you need to prove uh a divided by b* c and to prove that we cannot be further away than c from the real value. Um and I'm going to walk through you through the code quickly. Um and basically the way it works like you just import z3 right then you have a bc you define your integers the the ones we have and you can make some bounds. So in my case, I just want them to be bigger than than one. That's that's enough. And then I just uh put the two things I want to the two formulas I want to compare. So the

computed one on chain where I don't do anything. It's going to do integer math by default and the real one where I convert from like two real values to get the actual real um the real value result and then I can compute the error and the absolute error. Um and then I can add a new condition. So basically what I do is I add I have this solver which is the solver from these three and we're going to solve for all these um inequalities or conditions. Um so now we have like two condition like or four conditions right we have those four and we also want the absolute error to be um greater or equal than C um where the absolute error is defined like this. So you just

can put some Python math. You put your variables, a bit of Python math what you want to look at and that's it. Then it's going to tell you you can call the function check and it's going to tell you is it satisfiable like can we have A, B and C which are going to satisfy all those conditions or can we simply not and if it says you cannot then it means that there is not a single A, B and C um which are going to satisfy this. So in our case we this is asking can the absolute error be greater or equal than c um and if you run the program it's going to say uh unsat this means that there is not a single a b and c which are going to give you an

absolute error bigger than c so you can be sure and this is for a simple formula right but you can imagine that if you have a bit more complex math or if you have operations in a different order it makes it really easy to say Um yeah which number you cannot reach and if this is fine for you um and now like to be sure it works like because you now you don't see a counter example you don't see anything you just see unsat like can you really believe it maybe I made a mistake in the Python script maybe there is something wrong well maybe your intuition is like you can be maybe like at 999 of C so you just do the same thing but you replace um C by 0.999 of C and now instead of saying unsat, it's actually going to say SAT

and it's going to give you a counter example. So you can be at 0.999 of C with uh this ABC. So makes it quite easy to to check your formulas. Um let's look really quickly at a more complex one. But basically this is the OZ formula we just saw before. And the goal is to prove we cannot be because I said we can be higher than the this for formula compared to we can be higher than a * b divided by c. And so we have the same setup right we have the same computed wheel where I put this and now I want to show that we cannot be um 100% off. So we can be twice the real value. This is going to show again um unsat. We cannot find A and C such that we are twice as

high as what we should be. But we can find A, B and C such that we are times 1.99999 the real value. Um so we can be nearly as twice. So twice is like the bound how far we can be off in terms of uh rounding errors. Um yes and this is actually all I wanted to say today. [applause] Thank you, Yiannis. Uh, do we have one question for Yiannis?

>> Yeah. [snorts] >> Um, my guess is that if you have a very complex problem with a lot of operations, probably solving this is MP hard. So I assume that you cannot have really big programs. So could you could you share how far you can go with with this solver? Have you do you have some experience? >> Um uh no this is actually quite hard question. How far can we solve right? It depends of the power that you have. It depends of it depends of like for this when we're not asking to maximize like we don't ask to maximize. You can also ask Z3 to maximize. So to find these two

for you this is a really hard problem. It's going to take a lot of time. I think it's basically doing some smarter binary search and trying to solve the the the conditions for you one by one and getting closer. Uh this is really hard to find those for most formula that like go into one line and you just want to know the rounding errors. This should usually work. But if you start to model some really complex liquidation system, uh then first of all, it's going to be really long to model. Um and second of all uh it might not be able to uh tell you um or it's going to take too much time. Yeah.

>> Okay. Uh please round of applause for for Yianis. [applause] >> Okay. Yeah. I think it's a pretty relevant topic like the last balancer hack for over $100 million was powered by a rounding error. So keeping these kind of things in mind are particularly important nowadays. Okay. Uh next up we have Doris Benda. Uh Doris is a PhD with over seven years of experience on blockchain systems which if you consider that Ethereum is 10 years old, 7 years is quite a long time.

um she's she works at Concordium and today she's going to present about extending uh bulletproof your knowledge protocol with set non-s set uh membership proofs and she's going to go particularly into implementation security pitfalls and especially around how to make the thing non-interactive without shooting ourselves in the foot um okay as soon as people settle I think that we can get started okay thank you Doris >> hello Okay, can you hear me? Uh, hello everyone. Um, I'm Doris. I'm a senior software engineer from Concordium. And what we have there, we have like wallets. And these wallets, they hold real world identities. Like, uh, think about your passport for example. And the wallets can generate CK proofs about

these things. And we have verifies for that. And I want to show you something that we have implemented um to generate these proofs. So in particular we use bullet proofs um for um doing set and non-members like set membership and non-membership proofs and um first of all whenever I talk about an example I want to that you look at the right thing it will be like your think about your your passport in your in your crypto wallet that will be our example for the talk and to go back to the topic there were like two things so I want to like break it break it down we have like bullet proofs I will talk a little bit about background about that and set membership and non-membership proofs what that means So first of all um you have maybe heard about a bulletproof protocol. Um there's

like a research paper a few years old and they have an example given for range proofs and that's what most people use it for. And range proofs means you have a lower limit and an upper limit and you prove that your secret val value is in this range. So usually the most basic example would be like proof that you're older than 18 years old without revealing that your date of birth. Um I want to show you something new because uh that would be boring if I just repeat a research paper. Um, I want to show you how to use like a um non-membership proof or um like a set membership proof or non-membership proof and how to transform it so you can put it into a bulletproof protocol and proof it with that. So what is a non-membership or membership proof? Um um it's like

something you have a public value and you prove that it's an in an element S is like a set S and like a negation would be like you prove that V is not an S. But in reality, I want to actually show you that um what is a se knowledge set a membership proof. And what it means is that like your value v is actually a secret. Your your set is still a public um um kind of value like everybody knows that the proof on the fifth knows the the s. So think about it like you want to prove that you're a European Union citizen without revealing from which country you're from. In that case, you know the the European Union, you know which countries are in that set, but you don't know like you don't want to reveal your actual country where it is from.

Um also I want to first before we start um kind of give you an overview that like no no no protocol is useful for everything. So there are some specific areas where I would recommend to use these bulletproof protocols and that's um look always usually at the the kind of cardinality of your set like how big is it. If it's very small then um I recommend to use some some basic protocols like sigma protocols for example and use um kind of repeat them on like a few small kind of values that you want to test and use an or adapter to kind of link these different um proofs together if you have very large threads. Um on the other hand of course you don't get around to like implement some kind of trees. So like there's something what our cryptographers recommend it's like the curve trees that

is a research paper um I'm not sure if already it's implemented that's something you can use or like um if you want to use something that's more in production already there's of course the incremental merkel trees that um kind of toadocach is using like with nullifiers or if you need to something to prove something that's non-membership then you probably use something like sparse merkel trees there's some kind of implementation also how to do this in your knowledge but for for our kind of case we are kind of in the middle middle spot that means we have um a uh kind of a few already um countries like a maximum 200 countries but the set is like not huge and in that that area like these bulletproof protocols are quite efficient.

Um okay from from the next kind of slides what we will continue on is like we will from now on always think about numbers like every everything is a number. So for example you prove like a a number is in in a set of numbers and this is like very easy because like every kind of for example country code you can just translate into bytes and then you have some kind of numbers and there's also like two math notation I want to repeat so I don't know how far your math lessons is back. So these these two mass notation are related to like vectors. You have two vectors and in the middle here is like hadama product this kind of circle. Um and what it does is it means uh when you do a hardma product on two vectors you will still get a vector out of it. Um yeah

like you multiply the two elements on each position of these vectors and the element what you get out is like still an vector and a phenot for for this talk I think. But for the cryptographers and you like usually when you do math it's always like modul to a number like the Q here because we infinite fields. Then the other math notation I want to show you is like the inner product. It's probably even more important for bulletproof protocols. So the inner product between two kind of vectors is like you also multiply each vector at each position and then you you kind of sum it up. So what the important thing is here like the the result of an inner product between two vectors is gives you like a number in an infinite field. Um yeah. So I also gave you an

example to kind of if you if you want to go want to go through that. Um okay like let's go through like the the core idea of the bulletproof protocol to understand what what it does. Um so the bulletproof protocol it belongs to like um a CK kind of group of um protocols which do something like a commit phase and then a reveal phase. So the the first phase which is a commit phase um you put in your your secret values um it's usually some some vectors or numbers and important thing is as well to know that actually they don't need to be secret um in most cases you want to have them secret um but it's not a necessity in some way. So you have these two vectors and you have your your C which is your number and you put them into a commitments um think about it

like a sealed envelope. You put them in and close them. That's your commitment phase. It happens on concordium when when the account is created. We kind of commit to the to attributes values of your of your passport to kind of the fields. Every field in your passport is committed to. And then you have the second phase. The second phase is when you uh generate a proof and also the verify proofs um proofs like checks the proofs. So in the re real phase um the the proof of course has access to like your your secret values and the commitments and it can generate a proof and then it sends the the proof to the to the verifier and the verifier also has access to the commitments of course not to the secret values usually it doesn't make sense otherwise and what the verifier then can can do it can say yes or no and it says

yes the proof is valid um when this kind of inner product relationship holds in in in the envelope and the important thing is it doesn't open the envelope so it doesn't know the A, B or C. It just can say like okay I I'm convinced that you actually these these values you have committed to are following this mathematical kind of a relationship. Um so to to understand what the plan is for for this talk is like uh we have these set me on membership and non-membership rules and we want to kind of translate them into a mathematical equation so they look like an inner product relation because once they they in an inner product relationship we can put them into the bulletproof protocol.

So that's the first step we do that we go quite in detail I think um to understand how the the kind of constraints are for for this problem how to to write them. The second part would be then if you actually have secret val in our case like some of the vectors should be secret you need to blind them that means to make them actually a secret and then the third step would be like uh plug them into the bulletproof protocol and once you're an engineer you going with the fourth step you actually need to make the the kind of protocol non-interactive you have to implement it in a way to um yeah usually it's called like fear charia transformation we call we can look at it later okay let's go for the first kind of step what you want to Like the the first goal

is we have this kind of um converter. We we start with our left problem. We know V is an element of set. So how do we write this into like two vectors that it is to the inner product to C. Okay, we start with the beginning like the the start is like how we had the problem so far like our set S is like a just some some elements in there and we know there's like one V that's equal to one of these elements in the set. So we can write these uh sets that we have in a vector. So like left is like the the set the set kind of vector with all the elements. Um that's actually I think it's a bit shifted. I don't know the um the S value is actually public but the AL vector is a secret. And what is the

AL vector? It's like just zeros and one element is a one but otherwise it's just zero. And the the position where it's one is exactly that point where we initially said like our V is equal to SI. And when we have these two vectors we can actually like do the inner product out of it. And uh if the inner product out of it gives vi then um we have kind of uh written down mathematically that we know now vi is actually one of one of these elements like si and yeah so like you we could like think we have finished now but there's still a lot more we have to do because whenever you have a special vector like this like a vector with consists only out out of zeros or ones you actually need to constrain them further to make sure it's uh in this format and not like uh people

to put in other numbers. So the next slide is really just how do we constrain this AL vector that it is exactly in that format and for that we define another vector which is the AR vector which is just sifted by one. Uh you can look at the the right left there I wrote it down how the how the vector looks like it's just it has a lot of minus ones and one zero and then we have a few more equations to ensure that uh yeah these these kind of um the AL vectors actually from that form. So the first equation is like just our definition from above to to write it down that it actually holds. Then the second kind of constraint is that we make a heatherma product which is that like each of these values al or a r one

of the elements at each position has to be zero. And that constrains the al vector to just have zeros or just have ones. And then the last equation is there to make sure that we actually have one one in the al vector not more. And with this kind of equation, we actually have now the whole kind of problem written down in a constraint system and um we could plug them in into the bulletproof protocol. There a few more steps because in in reality you would make a really big inner product out of it. At the moment it's like kind of four equations. Um yeah, but I kind of skipped through that. So if you're more interested in it, you can read a blue paper how to do like several constraints into like one big constraints to make it one inner product.

Um now we go get to the second problem which was like this non-membership problem. You would maybe think it's the same way but actually this problem is quite different. We need to do it in a different way because it's this time is it's very hard to say like uh we cannot make V equal to any of the elements in SI. So we write the problem into a little bit different way. We say okay we don't know any AI that V is equal to SI. And uh when we shift the si to the other side of the equation then we know that the difference between these two two values can never be zero. And then we do a little bit of a trick because when when we know that something is not zero there must be a multiplicative inverse element that the proofer can find and

when when it multiplies it it will give like one. One is like the identity element in in in a multiplicative group. So you can also think about uh kind of natural numbers. If if you have a natural number, you will always find like another number that you can multiply with to give one except you have of course the zero kind of element to begin with. So if the proofer finds this AI value and kind of uh gives us it or like in the constraint system is able to plug it in then we know um we have kind of fulfilled our non-membership problem and have proven it. So if you write this into kind of vector form as well because we want to usually get these inner product um forms. Then on the left side we have like our public set again um that's the proof on verify

knows h they have previously agreed on the order of the elements so you cannot shift the orders around of the elements and then we have the a l vector and the a r a r vector and especially the a r vector is the the secret one uh the a value vector is like uh yeah it's usually also secret um yeah the a vector we don't need to constrain further so like the proof is allowed to kind of choose any element as long as like um yeah the multiplicative inverse to to the other side to the difference I would say and yeah the two constraints we need is like the AR constraint to make sure it's actually like a vector consisting just out of these V's the secret values and then we have like one constraint we can which

connects the AL vector with the I A R vector and in that way we can like uh describe a non-membership problem into like a constraint system and then convert it in a long way into like bulletproof protocol. Um, okay. Like I give us some tips because you probably a lot of you are like auditors how to like uh review these kind of things or like what uh often goes wrong when you implement these things because uh we also have to learn some stuff the the hardware. I feel like when you implement it the first way like of course over the years you get better. Um, I think one one thing you always can look at is like you if you have any kind of special vectors like in our cases of course these AL vectors consist of zeros and ones always

make sure they're like constrained enough. You usually need a lot of extra um constraints to make sure they they're in this form. Uh especially in the bulletproof protocol if you go to the second um point um as I said like the vectors don't have to be secrets. So if you have to read the kind of conditions of your requirements if they are secrets make sure they're actually blinded and people have done this kind of last step to make them secrets. Um then the next point is actually what from an engineering point of view we actually struggling the most by now is that like at the moment we are like at protocol version four in or CK proof version 4. uh that means over the time of uh implementing these stuff you you kind of um add new stuff and get new kind of proofing systems to it and if

you don't version the stuff uh enough it is very hard to kind of reasoning about it that um an old kind of proof cannot be used in a new flow. So I really recommend to to you like if you out audited this stuff even if it's like not initially a security vulnerability if you implement if you review it for the first time really tell the people like version new your commitments version new proofs version your context whatever you have probably it's a good idea to kind of version it especially if it could change over time and it really avoids that like people use older proofs um that have been generated in the past on on kind of newer flows in your protocol.

Uh another thing is like of course whenever you you kind of uh have some sort of randomness blinding make sure they they done correctly like uh you need to have fresh randomness they need to be uniformly um um kind of distributed usually there's something we call the Merlin transcript so I really recommend you to read about it because they were quite good in writing down how to do this well h never reuse any kind of blinding factors or any randomness you generate like generate once use it once in your commitments and never again and then there's this next step or like next transformation which is would be like a fourth step I would tell you what would say is um it's called fear chari transformation and um people use often these Merlin transcripts and there's a lot of things happening here that can go

wrong so I will go a little bit more into detail in the next slides what this fia chari transformation is actually about and in general there's a things you you should make sure that you actually have implemented all and put everything that's public into this transcript like generators keys that everything that has been transmitted between the brewer and verifier make sure it's in the transcript and there's also like stuff like uh make sure variable length data is prepended by by the length and um everything's domain separated as much as you can. So maybe to give an uh bit understanding what is the fear charia transformation um and why is it actually complicated to implement it the thing is that like most of these academic papers that we have as a kind of blueprint to get started with

they're written in an interactive way. So they written in a different way than what you actually have to implement it. So they're written and then something is that just a sentence which says like okay now apply fear charia as an engineer and implement it and yeah I think if it wouldn't be the diff the case that we have these like different things that we that we implement to what is actually written in a in a blue paper or like in in your academic paper it would be much easier and to to to understand what's what's a fear chamia like on the left side we have the interactive version that means like the proofer and the verifier are there and they're sending messages between each other. So first you you send the commitments then later the the verifier will send the challenge back. I

think this is a bit shifted. It should be a little bit up. I don't know why. Um and then the the proofer or like the proofer will send the proof and then later the verifier will send back if the proof is valid or not valid. So this is the interactive version and what you actually implement as an engineer is the non-interactive version. That means you start a transcript. uh you give it some domain separation for the proof that you have and then the middle part it's the hard part you should put as much as possible into this kind of transcripts and it means like for example everything that's uh all the messages between the proofer and the verify need to be put into into the transcript or all public values it means like um um your your curve points for example the generators or if you have any kind of public keys

everything has to be put in there and then when when you actually need a challenge from the fifier you would like hash your kind of transcript which is just appended bytes for now on and that's what you use as a challenge uh on the proofer side and in that way you can kind of avoid this forth and back communication between a bofer and a verifier and you would only have like one communication channel which means like the proofer will send one message to the to the verifier that's a proof and nothing more and that's why we implement this non-interactive version because like yeah we don't want to have that much measuring between proofers and fifers so what couldn't get go wrong like when we implement this fear charia I mean the most basic or most severe problem is probably that you forget to

put anything in this the transcript that should be there. That was at the beginning when the bulletproof papers came out. They actually forgot a little part to be in input in this in this transcript and there was a lot of bulletproof implementation. They were actually vulnerable and it was fixed after a while. They gave out like an updated paper and it it was fixed. But it was like the biggest I think problems in the beginning with these bulletproof protocols and channel CK protocols that you forget something in the F char. Then I go into like another example which might be not very obvious is that whenever you add kind of add anything that's variable length to to the scrum script. Make sure you add um your kind of length of the the items that you add.

So I give you here an example um you'll be adding strings. If you just add uh a a bb they will be like generating the same hash than if you like just add a and then another string with a bb. So make sure you add your like uh length beforehand then there can be no like hash collision when you actually generate the challenges. Um the other thing is like just make sure you you add enough domain separation enough labels to it that that kind of allows you to to change things later in in the protocol. make sure that like a previous label or thing you have added doesn't like overlap with another um kind of value add later. So I also recommend you to like look at the domains and labels a lot and in general like whenever you have to implement it

like please read the Merlin transcripts they have some write up it's quite nice. >> Yeah that's me I hope you got something out of how to review uh zero knowledge protocols and bulletproofs. So any any questions from your side? >> Okay any questions for Doris? Yeah you have mic. Yeah. So, um I see some similarities with Merkel trees where you can proof existence of some element into the into the set. Um I was wondering in what cases it's better to use bulletproofs as as opposed to Merkel trees.

>> Yeah, I don't know if you were here at the beginning uh like there was one slide where I tried to uh give an overview. Yeah. When to use which kind of protocol. Yeah. So, it really depends on the size of the set. Um if you have very very large set you you have to use trees. Um and if you have kind of a mediumsized um set then I think you can use bulletproof protocols. So in our case we use it for for the countries and for the nationalities of the the passport information. So it's like max 200 countries I would say. So our set is like that size.

>> Okay. Any other questions? Yeah. um like like your your slide says it's best for the cases where you have max 200 could you a bit elaborate on uh the difficulty is it prover site is it a verifier site the complexity of it why 200 >> I mean that's not a hard limit I just say for our use case it's 200 but yeah I I don't actually know exactly like where like we haven't done any kind of simulation where we say like how far we should go with these kind of bulletproofs and when we should stop the Nice. But it would be actually quite interesting to get some benchmarking see like at one point you really say the bulletproof protocol shouldn't be used anymore.

>> For example possible onchain. >> Yeah. The thing is like um verification we do offchain. So our fif are back ends but it's really because we work with um um kind of real world identities like a passport information and we could we could like build a verify onchain but the thing is you kind of leak indirectly information. So for example, if I interact with a DAP that wants to prove that I'm that I'm older than 18 years old and I interact with the same account with another DAP that maybe proves that I'm from from from European Union and then another DEP at some point people kind of know where I'm from, you know.

>> For your case for your case, but there are many other cases where this is not a problem. So I wonder if verification is fast enough >> to and cheap enough. Yeah, I think it's super fast. Like I mean the fifers are like rust back ends and uh for for generating the proof it's like the wallet pops up and you just click approve. So it's the same flow than sending a transaction on chain. It's not that there's any delay in there. So the dev will say generate the proof and then you click approve as a user in the wallet and the proof is generated and verified. So it's there's no delay. It's maybe one second late maybe less the proof generation verification.

Yeah. >> Okay. I think we're on time. Thank you so much, Doris. I I love the the security overview at the very end. Um I think it applies to a lot of domains, not just zero knowledge. So [applause] awesome. >> Yeah. Yeah, absolutely. Thanks. Um okay, and last on this blog, we have uh Kirk Bird. Sorry again, I suck at pronouncing names. Um Kirk is going to go through uh basically an overview of the risk zero VM. um basically a security oriented overview and how to avoid pitfalls on it. Um Kirk is director at Sigma Prime also with seven years trying to break blockchains and so okay I'll let you

take it. Beautiful. Thanks Pablo. This is the last talk of the session then we can all go out for a little sweet treat or some little snack in the break. Um so first of all uh you guys heard Jeffrey earlier on in the session. Uh this quote is from him, but he was quoting someone else. And so I have absolutely no idea who originally said it. But if crypto goes to zero, at least it gave us zero knowledge proofs. Uh zero knowledge proofs are great. Uh they're they're absolutely unreal technology and um risk zero is what brings us to everyday people without needing to do maths. Uh if the last talk was too math heavy for you all, uh I'm sorry. It was great. Uh it was the right amount of maths, but this talk won't have any maths at all.

uh you'll feel relieved. Now, uh what is risk zero? Uh how does it work? That's what we're going to be looking into, but really going to focus on applications as in people who have written code for ris rather than diving really deeply into the riser VM. So, the type of architecture and the theory that we're going to be looking at is what people need to review and write uh ris. Second part will be a coded example, run you through uh how bad I am at a developer and how many bugs I can write. You can hopefully spot them all out pretty quickly and then we'll go through them together. And then at the end we're going to be running through all the security tips and tricks and everything else you need to know. So theory basic risk zero architecture. Um what are we

actually doing? the risk uh the virtual machines any sort of ZK virtual machine is going to be proving that a certain part of execution happens and think of it as a smart contract which is going to be a really good analogy through this thing you can prove that the smart contract executed and there's an added benefit that any of the function parameters the inputs can be private and can be hidden. Um, why is this so good? The the biggest why is actually the compression cuz we can do an entire program like huge I'm talking about hundreds of thousands of lines and we can output that into a single verify line which is a little bit of maths BLS and a few other things under the hood

and can run very comfortably on a smart contract in about 100,000K gas. 100,000 gas. Nice. So, how do we actually do this? Uh, what you got to do, you write code. And the best thing about riso, it's in Rust. Uh we all know and love Rust. Well, most of us do. It's an excellent smart contracting language. Um and what else you could do is you can compile it into VM code. Uh they use ELF and Risk 5 for for this. And with that code, you can send it over to a prover. The prover runs it and gives you output this little receipt.

So I'm kind of going to break these into like two main types. Uh we got those that are general purpose which is risk zero writt in rust happy days uh you can write your code in rust then we got the other ones like domain specific languages um that's cyros VM Aztec uh miden and aloe they all use domain specific uh zkvms which uh the trade-offs here are that you have to learn a specific language for example you need to learn cairo to write on starknet and circuit based languages they're challenging They're they're actually really hard to write good code.

You need to know a little bit more about the maths. You need to know about finite fields and you really got to be strict on writing circuits and constraints or else you're going to put some bugs in your system. That does not happen in risk zero or SP1. You write rust and some other really smart guy has gone and done all the circuits for you. So it's happy days. Now uh let's get into the architecture of provers versus verifiers. So provers are the people who are generating proofs. Oh wow, what a surprise. Uh well named actually thank you. Uh these run the programs. They need to have full access to all the inputs. That includes the private inputs. If if you need private inputs, your prover will know what they are. Um and then they can be split. The proof

gets split into two components. The guest code which is actually what's proven and then the host. And of course they output a receipt which is a proof uh mathematical proof. Small little thing. The verifier, on the other hand, all they do is check receipts. Yeah. Yeah, I know. It's your accountant. Uh all they're doing there is running through a receipt, making sure they work. They do not actually execute any of their code. The code is assumed to be correct. If the proof is correct, uh real important here, they should never trust the prover. Uh if you're you're relying on the prover and any sort of thing from the verify, then you're probably going to have a very centralized uh broken system.

Cool. So let's look at this nice pretty diagram. Uh host and guest they're inside the prover uh yellow and then we got the verifier in blue that does the maths. The host is a normal program. It has access to the internet. It has access to your database, the real world, whatever you want it to do. It's just a regular old program and it can call the guest. Uh the main function of the host is to prepare all of the variables that need to be given to the guest and then the guest is the code that actually gets proven and this is taking inputs. It's think about the EVM. It doesn't have any access to the outside world when you're in a smart contract. That's the same as a guest code. All it has access to is

what the proof gives us. Uh sorry, the host gives us. Nice. And then the guest outputs a little receipt. So uh some of the things that pop up a lot in the space are receipt journal and image ID. The receipt is the proof I've already told you about four or five times. Uh the journal is uh what we call the public outputs. So as I said uh the guest can have some private inputs. It can also have some public outputs. So these are things that it really wants to share for the real world. And we'll find out very shortly why that's helpful.

Next up is the image ID. The image ID is unique to every single wrist zero program. Why do we need this? Uh because if you write a program, I write a program and some hacker over there writes a program, we want to know if the receipt is verified for my program or it's for your program or it's for his program over there. Um so if you don't check the image ID, someone is going to make a fake program and and wreck you real quick. Cool. So jump into it. Little bit of code. Fun fun. Um, these are the main functions that you'll use in the risk zero crate. Like this, this is literally all you really need to know to audit risk zero code. These six little pieces of information. Super easy. First one, entry point. That is

just defining where you start your guest code. All right. Uh, yeah, guest code starts at a main function. What a surprise. Nice spot. Next up, we have the read. This is what I talked about. Private inputs only. Uh, EVM commit. This is putting to the journal. Anything you put in that commit is going to be public for the world to see it when they receive your receipt because it's written to the journal. Uh those top three are all for the guests. Next up, this builder uh executor environment. This is what we actually use to uh build our guest programs and so that the prover next up can call prove over the environment. And then finally the very last point is the verifier. All they really do is check this proof. Um, under

the hood is going to be some nice maths. Woohoo. Made it to the coded example. This is where things actually get interesting. Um, this is what we're trying to do. Prove an Ethereum address has more than one ETH. Uh, little bit of criteria. Fetch it via an RPC. Check that it is my address and the verifier has a trusted block. So, let's start off with this. This is full of bugs. Uh if you write this, I'm going to be real mad at you and and give you about four or five critical bugs. But let's look what it does. The first uh piece of code that actually executes is going to be the host. Sequentially, the host is always first because they need to gather all of the input variables that we put into the guest. And as you can see here, uh first

thing they do is they do this RPC call for some address and they get the balance. Next up, they write that balance into the environment. hit the build and then the prover can prove that prover.prove step is when the guest code starts executing. So it will specifically happen after the host which makes it a little bit hard for the host because a host needs to get all of the environment variables in order before they actually call the guest. And then finally after the guest has finished executing it's going to return a receipt and that receipt can be verified by the var uh the verify.

So what is the first bug that we we see here? Uh the first bug is that the RPC call is done in the host and that's where we check the address to the balance match. This is not done in the guest and therefore the verifier cannot verify in any way which address this balance is for. This balance was meant to be for my address, but I could use italics because I know he's got the bags. So let's touch that up. Let's also write the address in here. As you can see that second line, the host is now uh putting the right of the address. The guest now reads uh the address in the same order.

The address came first and then the balance and it can now commit the address to the journal. The verifier is able to extract the address out of the receipt and now it could do two things. The verifier will now check the address and it will also verify the receipt. So we are using the public journal here to do things that we cannot do in the guest. Um the guest couldn't check this address that could only be done in the verify. So they put it to the journal and said all right verify this is your job. I don't know how to verify this thing. You verify it. However, there's still more bugs in here. Is anyone seeing some bugs in the guest code?

uh in in a guest code >> the the host has access to the internet. The host is just a regular Rust program that's that's allowed to say anything. So it's it's allowed to hit this RPC. >> Yeah. Yeah. We we we don't have any checks between the balance and the address. The address just comes in and there's a balance there. So next up, we need to do a proof inside the guest program that ties those two together. Bam. So to do that, we actually need to do a bunch more things. Uh we need to get a balance and a proof from the RPC.

Uh let's let's just assume that happens nicely. And then we need to pass all those things into the guests. To do a proof, uh you you need quite a few things. Uh you need the balance, you need the address, you need the block hash, and you need some sparse Merkel tree proof. If you've ever looked into Ethereum and how how to prove an account's balance before, it's it's just basically a giant Merkel tree. a little bit more complicated but really not that much. Um so inside the guest again we read everything in the same order because or else our program won't work and then we do verify account proof. We do that whole Merkel tree and now we have very happily tied the address to the balance. So those two are tied together. Happy days. We can commit the

address and now the verifier is like okay thank you that that address does have that balance. We're all good. Now, this this is looking pretty tidy code at this stage. However, there's still one very subtle bug. Uh the subtle bug is that block hash. Uh we have absolutely no way to tell if that block hash is real. The guest the the host could have lied and just put some arbitrary block hash from FC Classic, any other chain they wanted to, and this proof would have gone through and be like, "Yeah, yeah, that's that's what the account balance is for this block hash." So what we need to do bam is actually commit that block hash at the end of the guest because this is something that the guest

cannot easily verify. How does a guest which is just a small little smart contract know if a block hash is valid. It's the tip of the chain. It's the canonical chain. It hasn't been forked. These things are all extremely complicated to do. But for a verifier um maybe they could do them quite easily with a light client proof, something like that. Fality proof, something along those lines. Happy days. Uh the verifier has done this and now we have the most secure ever balance check. And so to highlight what the benefits actually are, as you could see this this guest code uh takes in a lot of inputs and it also does a very big account proof which is going to be a whole Merkel proof. And

the verifier on the other hand is just what like four lines and some little BLS logic in there. That's the compression. That's the main reason that we use uh onchain proofs is because you're able to take a really big guess code and put it into a tiny little line in the verifier. So if you think about it in the context of an L2 uh ZK roll-ups, ZK roll-ups, the actual node implementation is massive, hundreds of thousands of lines, their guess code would be absurdly big. However, onchain they can just have a verifier that's just a handful of lines that does that. So this is the main gains. uh that we get to see. The other gains are if you want to optionally hide something like I don't know the claim

balance amount or something like that, you can have some private inputs as well. Cool. Last section almost for time for a sweet treat. All right, so the host rehashing untrusted by everyone else. No one should trust the host. Uh it must put everything in the same order. Uh it reads it. The main security bugs that we're going to see in the host are chain halts. It's going to be DOSS vectors. Uh there's going to be things like panics, error handling, what happens if the guest code is fail, writing things to the guest in the wrong order, which is just going to cause everything to fail and revert hopefully.

And then in the guest code, it's really about input validation here. Uh I've called it under constraint circuits. That's a little bit of a bastardization. I'm sorry. Uh it's just input validation. Any input that's not happening in the guest code must happen in the verifier or it doesn't happen at all. Write anything to the public journal that you can't verify. So the verifier can do it. Uh the verifier has three important things. It must read the receipt. It must validate the journal entries and it must check the image ID. Uh it verifies anything the guest can't.

So if I go back to this line, you could see that in the receipt. There's balance ID. This is the image ID. I've set it as a constant as you could tell by the big writing and it's fixed. If that image ID was passed in by attacker, they could actually make a proof for any program at all. So, it's really important to do a lot of verification of your image ID as and so it should be what you need it to be. All right, tips and tricks. Guess code is where most of the big scary critical vulnerabilities you're going to find. Guest code is where the juicy things are because that's what the maths is actually covering. Uh, and in risk zero, it is a 32-bit OS. And don't forget, if you're in Rust, everything is going to wrap by default arithmetically

when you have that. So, you really got to look out for 32-bit. Uh, 32 bits is only 4 billion, by the way. 2 to the 32. It's tiny. You can brute force that. You can do anything you want to it. Turn on overflow checks equals true on your cargo toml because panicking in the guest code is happy days. I'm not sure if many of you have looked at salan or near. Similar principle. Panicking is a valid form of error handling only in the guest. If your host panics, well, you're going to get a chain hole. Um, next up is library dependencies. If you're in a guest code, as we said, you don't have access to a lot of things. That includes randomness, files, all of that things.

And although you might not have written it yourself, if you use a third party dependency, they probably have. And that includes things like threading. A lot of cryptographic libraries use threading to make the cryptography runs faster. And if you don't realize they're threadling threading, you're going to get probably compile time errors when you uh try and compile your guest code and you'll be like, why is this library not working? Oh, sad face. Cool. Resource exhaustion. Uh the prover is running the guest code. The provers is a lot of the times not going to be you. There's going to be some beefy machine. Proving is really expensive. You need big beefy machines and they need to do a lot of work. So if you have any sort of unbounded loops, really unrestricted string lengths,

arbitrary uh data inputs that use a lot of resource exhaustion, a lot of resources, it's going to be super expensive for whoever's running the prover, which is probably not you. Unconstrained circuits, we've already talked on this. This is input validation. Uh make sure you do everything. And then again, anything that can't be validated inside the guest code, we send to the verifier. All right, this is your checklist. Uh, this has pretty much everything you need to know to review a riser piece of code application.

Start out at the top. Critical logic, all inside the guest code. Um, we've covered this. All inputs validated inside the guest code or written the journal. No private information written to the journal. Don't want to leak secrets. 32 bits. Never forget 32 bits. Computer's expensive from user input. Uh, the verifier has those three main points. We talked about them recently. And finally, the host must write to things in the same order as the guest. I'm going to highlight this one for you.

Um, right here, we we have four pieces of information that we're writing. But if you have um say 100,000 lines of code, how do you actually get your host to write all 100,000 plus input variables in the same order that the guest's going to read them? Uh in Rust, you're going to do this by generics. Uh the the best way to do this is to have one generic and you actually run the host code exactly the same as the guest code, but the host code generic will write things into the environment variable and the guest code will read from the environment variable. So it's like a a little bit of a switch that happens at build time and that's pretty much the only way you can do it for

large projects. Cool. All right. Uh handle the case when the prover fails. When the prover fails, you're going to get an error. uh in your host code which is running the prover uh that's fine. We can handle the error case uh errors for a whole bunch of reasons but you don't want to panic. DOSs vectors error handling redundancy and proofs are inherently replayable. Uh that means one proof if it's valid once it's going to be valid forever. There's no nons checks or anything like that. That's all up to the verifier to handle if they want to do uh replay protection.

There are some good resources. Uh if you want to see these slides, there's Google Docs. Some other sources, uh there's a blog that I've written not too long ago on SP1. It's essentially covers a lot of the similar things from Riser, but it's on SP1. Um ne next up is the rare skills boot camp. Uh if you heard Jeffrey talking earlier, it was at the start of this session. Uh he's a great educator in the space. Uh he runs a boot camp on all of zero knowledge. It's an excellent entry point. There's also a ZK book if you don't want to sign up for a boot camp and you'd rather do it in your own time. Uh the book is free as well.

Lovely. Siphon updraft courses. They've got some great zero knowledge stuff in there. Uh lastly, if you want to hit me up on Twitter, I'll probably respond to you probably. >> Thank you, Kirk. [applause] I have to say it was very bold of you to say that domain specific languages for zero knowledge proofs are hard to learn when you're opposite to noron you know but it's okay your slides game was very good I'm I'm willing to let it slide any final questions around here we're a bit past time okay one question let's go >> with image ID is that a hash or is there some central registry of image ID based very

>> sort of a verification key for the circuit. Okay, cool. Okay, well um that concludes the block of sessions around math and zero knowledge. I think we'll have a very very short break and then we move into institutional security. Um Lilian, I'm not sure if you want to say a few words. >> Okay, well thank you. And before we get started, we'll just talk a little bit about ourselves. Um,

I'm Julia with Zero Shadow. Zero Shadow does uh security prevention and instant response. So, we're trying to be your security partner for the entire life cycle. um if you're trying to make sure that you don't get exploited and if you do doing the tracing and the recovery of the funds. >> Yeah. And quickly about 1 in for those who don't know what 1 in is is uh used to be the biggest dex aggregator and at this Devcon is maybe will be a biggest liquidity uh layer in in DeFi after it and yeah we we are the set of protocols that do different stuff. Uh and uh what we take also very seriously is security uh risk management that we're going to also tell you about a bit in a bit.

>> Yeah. So what is the problem statement here? It's that your total value locked is entirely North Korea and that's what's making up your protocol fees. Um we saw this very clearly with the buy hack. Um we at zero shadow were the ones uh who were tracing those funds. And if we're looking at this, this is a overall summary graph of how the funds were flowing. And you can see that these funds hit a lot of different decentralized applications along the way. So, North Korea very famously always swaps all of their funds that they stole into ETH or some kind of um more stable and non-freezable asset.

Then they move the funds across chain. They use a lot of different bridger bridges to do that and they go across a lot of different chains in the process. We've also increasingly seen that they're using lending protocols as kind of like a storage spot to hold the funds for a little bit before they continue on with the laundering. And then ultimately they're trying to um exit via over-the-counter brokers um a lot of them that are Chinese-based. So along this way um this is a little bit of an ideological position but there are a lot of applications that we're interacting with um in this process and we're talking to them about um what they're seeing on their side um in terms

of these stolen funds moving and also if they have any way to intercept these funds or at least dissuade this activity from happening. And you can see that when this kind of activity happens it can be pretty drastic. So this is uh Thor chain movements in early October. There's suddenly a four time spike in the activity on October 2nd. That's because four different North Korea hacks were suddenly going through that bridge at the same time. So these are all fees that Thor Chain in this case are gaining a lot of um profit off of. And so maybe there's something that uh they want to do about it. Um, I think there's two real reasons besides it's the right thing to do that you might want to try

to intercept elicit activity. One is that the law enforcement is looking at these things. Um, and it's not just US law enforcement. So, at the end of April, we saw that EXCH was taken over. that was a centralized uh service but that was uh Netherlands and German law enforcement that actually took note of how much activity was going through and decided to take action. The other is the impact of institutional trade that's coming. Um there's been a lot of talks this week about how how much Tradfi and these uh institutions are planning to integrate a lot more with decentralized applications and they're just going to have caution if they see a lot of

Twitter posts about how one protocol is especially being used uh by bad actors. So um if you're in that position where you say, "Yeah, I do want to try to do something and take action against being used for illicit activity." uh then you might hit some kind of design barriers that are impacting your ability to actually implement these kind of changes. And there's a few that we see come come up again and again when we're talking to services about if they're able to do anything. The first is contract upgrade restrictions. So, uh, the way that the protocol was designed, uh, was pretty finite and it doesn't have really good ability to add some upgrades to maybe have delays or

freezing or whitelisting or blacklisting. These are all features that might be um, impactful, but there's this restriction in the current version of the system to actually be able to put that forward. The second is composability considerations and definitely there's um certain parts of your ecosystem that might be uh better used for actually trying to stop list activity than others. If your token is being traded across all these different decentralized exchanges and crosschain, maybe that's going to be very complicated to try to freeze funds, for example. But if you have a bad actor depositing directly into your lending pool, that might be a better scenario

where you can actually try to take action. And so thinking about those kind of more specific use cases where there might be a real change. The third is address turnover. So we see that bad actors are ripping through new addresses extremely quickly. for the bybit hack. By the first six months, we had counted 12,000 addresses that these actors had used. And so, if you're just using some kind of general know your customer, know your transaction kind of platform and just trying to receive blacklists or even via word of mouth, via someone in a Telegram chat with you saying block this address, you're just always going to end up falling behind

because the turnover is so quick. And then the last one is small teams. Um totally see it and know it that a lot of uh these teams are maybe one security person maybe not even and you want to focus on building and growing and not necessarily the security side. So that can be a huge barrier to actually implementing some kind of changes to try to thwart this activity. But we have some baseline recommendations that we've seen are working and um want these to be at least good takeaways and we can start a conversation if you want to think about what else you can do more specifically.

So the first is delay functionality. This is really really impactful that you don't have to take custody of any funds but you can just add some kind of considerations for making it harder and having more friction to actually move this elicit activity forward. So some of the delay functionality you could think of is by volume. How many of your users are trading $100,000 at a time versus $1,000 at a time? How many of them are doing that multiple times in a row? because we'll see uh five bridges in a row. They're each 500k. That might not be your typical user that's doing that.

So, you can start to make some special considerations there. You can also think about just having a time delay. Maybe it just takes a few more hours to do certain activity and that's giving you more time to think about um causing friction and making them maybe move to something else and away from your protocol. Also, address needs a nons higher than zero. This is a huge one and this is going back to the fresh addresses that we were talking about. If you have an address where it's only received funds and it's never sent anything before, you can consider having some kind of additional checks that you do before that address is going to interact with your protocol. Um, and again, I think this is one where if you review your

your system and look at how many fresh addresses are uh potentially illicit versus normal users who just continue to reuse their addresses, you'll you'll notice this kind of trend. Token risk categorization. This is the idea that if you know that uh bad a token with a blacklisted token is being used, you can just kind of exclude it from your data set. live blacklist. This is the idea um which Oris will talk more about about how you can make much more comprehensive and dynamic blacklists that go beyond just an address list and have a much more real time look at what bad activity might be touching your protocol. Uh it's

kind of like an oracle in a way where it's constantly live updating and you have that feed that's integrating directly into your systems. And then the last one, front back controls. The idea here is that you might just you might have multiple layers where there are um integrations with with your protocol and you want to make sure that you're accounting for those and you have risk controls at each of those layers. So it's not just the website, it's not just maybe the contract itself, but it's everything in between. Um so one case study here, um this is also from Bybit with Mantle. Um this was uh at the very beginning of the BBE hack. We saw that Mantle was able to

save 15,000 CME from uh being taken by the North Koreans. And in this case uh that was at the time that was about $40 million. So how did they do this? First of all, they had a delay window. So they didn't let the funds move right away. they had in place that they could not not freeze those funds necessarily, but at least stop the activity and have some time to take a breath and think about, well, what are we doing here and and what do we want to do next? Then they actually blacklisted the exploer address and then they had the ability to actually move those funds to a recovery address. And so the controversy here is that this is centralized activity. This

is not fully decentralized. And I completely see that. I think also it was interesting to see the community response um to this action because there weren't a lot of people saying in a very ideological way, oh we should never do this, we should let them take the money. There was a lot of I understand in this situation why this needed to be done or I understand that we want to help in a security sense. So I think that the ethos is kind of showing that there there is some degree that if you can do something that maybe you should do something. I think the balancer exploit has also shown that and the response that people had to different layer 2 actions >> and I can pick it up from here. Yeah.

For a while. So for what Julio mentions uh that one of the last things that Jul mentioned was very relevant to me is the front and back end controls. What we do at one we categorize security to three layers to the front ends uh to the protocol and to the back end controls. Not all the device has probably backands uh who doesn't want to have like back ends controls but we have actually because of main sync security and uh what we do sometime we we have a lot of security triggers on the front ends uh which even the site topic of conversation on the protocol level I think we are all as industry is not really there to have some some ML controls on a protocol level layer even if there was like a lot of controls but

on the back end level we advance a lot on how we uh controlling the identifying and screening of the bad actors in the space and uh this is what we are building uh at 1 in mainly the back end for uh screening controls and identifying of bad actors and we do that not just on the uh bad actors that been been identified by that scan or someone else last week last day last hour last minute in the space what we do we try to uh uh create build profiles around addresses and clustering at addresses and prevents the the bad actor becoming before becoming the bad actor on chain.

And this is thanks a lot to Zero Shadow. Zero shadow doing amazing job uh in terms of uh security and identifying patterns, identifying wallets, identifying uh different group of bad actors in the space and supplying us this data. uh we actually created even the direct uh uh supply of uh data to from zero shadow to the 1 in back end and they have a full access to uh the 1 in block lists but what we do like what the most probably biggest thing we are building right right now is one in that improving the security space uh in defi is clustering of different patterns in the space with also the help of inner

works so what does it mean it means that uh based on the uh log data we are receiving from interacting with our interface. We can cluster different bad actors wallets to under one category of bad actors for different type of profiles and by that we can say and report properly then on those actors say who they are and then report if needed. So uh what I'm trying to say that it's not the the control we probably used to have with such tooling/chain analysis term labs elliptic what we try to do we try to understand why this wallet was blacklisted and what is this wallet not like relying only on the data that

someone supplied to us and do that on the on the smart data or fingerprints. Uh yes thank you. So and uh also to do that successfully this is what actually we come up and do with zero shadow of we uh uh we preparing the playbooks for that and uh because we we we don't need we don't seeing that you know some probably uh discussions are happening in each country to regulate defi to put it under QC to to make the the gatekeeping window for defy protocols but we think that probably the most one of the most one of the at least ways to go would be to create a patterns patterns on what to do on the uh on the D5 protocol to make it better secure and one of the playbooks

is what Julia already mentioned token risks. Yeah, working with different type of tokens that uh different type of risks that identify different type of tokens to not let user use it. Uh transaction simulation this is what we do for for the 1 in wallet uh users. uh the the playbooks we are creating I don't know if you saw that but you can Google that you have one in security white paper and uh we are releasing new version two this is actually the the the playbooks controls we have it one in and we kind of sharing with with the community to to work on the same and uh post incident flows this is probably one of the most important is that when you have the playbooks you of course follow them but you cannot bulletproof yourself

from bad actors using you so what we do is uh after uh we identify any anomaly any bad actors patterns using one protocols is to isolate trades that we profited out of the user uh as the protocol as a company sometimes it's soft surplus as we don't have trading fees at one in it's only company funds it's not user funds because we are not custodial and then uh do some review and reporting with those funds can you only yeah >> um yeah So this is a case study which is showing some of that um enhanced address list that we were talking about where you're profiling

um how how the users interacting not just by their address but by their entire online presence. And here this they chose to remain anonymous but this was a large centralized exchange that found that their token was being laundered by bad actors. And you can see from the chart that these big spikes were really coming from a bad actor and that the the normal users were at a much lower um to volume of usage per transaction. And so what what happened here was that the laundering was deterred because of using these overall user heristics to really create these uh friction, create those delays for the

the bad actor to actually be able to bridge the funds and then the moment that the funds were a ever successfully bridge being able to actually freeze those funds. And so that really deterred the actor and they stopped using that that service and and uh they have much better uh statistics we could say after that. Um so one example there >> yeah this is coming back to the isolation. So and we will give you one example what for example we do and try to make other device when we're doing in the space because it's not that much popular uh for example protocols to do is in case you have some uh fee extraction you you make revenue out of out of the someone who's using a

platform as an interface as a protocol or whatever you are in defi you can also uh uh do something with those funds not keeping it for yourself yeah just for example uh give it back to the victim yeah which is always the good Okay. So in our case what we do uh we try to always isolate for example at 1 in we have swap surplus uh from every user who is swapping at one in uh and so we when we identify that this is a swap surplus from the bad actor's wallet we isolate and with the helpers with of zero shadow we also try to identify the uh the victims and give it back give it back based on the uh course order green light from the law enforcement in case we're coordinating with them or actually this

is Something that Zero Shadow is pushing with also security aliens and CL 911s is the coalition of different partners where you can identify each other before sharing for example the fees you're isolating in case one of the partner is the is the victim of of the hack and uh yeah so what I'm trying to say that uh this is the hygiene we do for at one in for the app and we try to also to h give the same hint to our our partners in defy to do kind of the same. Yeah.

And this is actually the case that we did once time uh with the with the one in uh for those who who don't know we have two kind of uh swap systems at one in one is aggregation. We aggregate among like all the available liquidity in the space mms and PMMs and one is intentbased. So intentbas is just make an intaker. Yeah. So we have resolvers who is providing liquidity in the in the one in fusion we call it uh intentbased phase. So that's why you see a resolver is usually a third party actor like uh I don't know winter mute cumberlands and so on. So what happens the bad actor before it was identified by anyone as a bad actor uh entered the one in DAB

space uh settled the make made an limit order. limit order was settled with the one of the one inch resolvers and one inch resolver make huge amount of fees out of this settlement. Uh they arbitrageed. So what we did we just uh uh isolated those fees and uh then after the investigation and law enforcement coordination we uh sent at least the part of the money that was stolen from the user from the user to this victim.

Yes. And thank you, please. >> Yeah. Um, that's it. If you want to talk to us about um any of these designs uh or playbooks or if you want to try to join this coalition that or talked about, which is trying to have um faster return of fees uh without waiting for law enforcement requests, which can take a lot of time, then just reach out to us. Thank you. >> Thank you, Julia. and arrest I don't know if there is any question maybe we have time for one any question >> okay thank you thank you again >> let's welcome Ilia chief information

officer at 1 Roxy govern and compliance specialist at zero shadow and event security and data protection officer at 1 uh same stage is yours Are you sure? >> Okay. Do you want to stand on top or >> I think just stand. >> Is it working? >> All right. Hello everyone.

Glad to be here. So today we will present uh lessons which you learned after passing through certifications ISO and so 2. But first of all let me represent myself. I am Ilia chief information officer from 1 in and we have also Ivan our security and data protection officer and also we have a Roxy a specialist from zero shadow. Okay, as you can see that the second presentation in a row where zero shadow and one inch partnering. All right, so let me start from a quick question for the audience.

Do you so do you have if you see some words which you don't understand what really means please raise your hand. Okay, which one? What's that word? Okay. Continuity. Uh, anyone else? I I saw one more hand over there. No. Okay. So, only continuity. Okay. That's very good enough. All right. So, yeah, as I said, we got ISO and the sock 2 type one certifications and u why we did that? So first of all that's a partners and our

clients demand pretty much obvious we are going to traditional finance and that's why we need to be prepared we need to be have a badges which will show our security pressure and so on and so forth then that's a pest to scalable credibility right how we are going to find new partners how we are going to attract new clients right so this certification not only this showing that yes, we are ready, we are compliant and so on. And uh last one but not least our original idea was pretty ambitious and enthusiastic that do this stuff right in terms that not only have a check marks

that oh we are compatible we are compliant right but also have that really in our company have everything what's being kind of pushed in ISO and so 2 uh into DNA of our Okay, so that's our short history. We spot demand in the 2023. We spent the whole year of a 2024 for uh transformation of our infrastructure. How we are building CI/CD deops and so on uh identity management. So that's took pretty much a while for us uh to be there. And in 2025 we uh proceeded with the process transformation and also we

already had obviously internal and external audits and our upcoming goals is by 2026 do have a second part of a sock two sock two type two to be honest that's probably will be a little bit challenging for us because ISO and sock two type one I would call it theoretical one and for sock two type two it will be much more harder. We will need to bring much more evidences and so on and so forth and uh uh also in the next year we are going to proceed potentially with other certifications which uh interested for our clients.

All right. So who was doing our internal audit and external audit? So first of all thank you to zero shadow right they not only did our internal audit but also they helped to find a very good external auditor prison security. All right so the first thing which you should know that to get there uh to be major enough that's a multi-dimensional journey. Okay. So that's not only check marks. You should be major enough on all listed directions, right? So you should for example work on the ownership at the

beginning when everything start up like uh everyone owns everything, right? But once you grow there should be clear um vision who is accountable for what. Documentation the same when you start documentation in people mind and as probably just a little bit in the code but once you grow you need to on board more people you need to be sure that everything is documented correctly that everything uh consistent with each other. So you should m became mature enough from documentation perspective um grow from a tribal knowledge to formal

and easily to automated knowledge. Next one of course that's a processes right at the beginning it's ad hoc processes somebody just pushing somebody else hey go and do something and there is no processes at all no processes and once you go you should understand what's repeatable things you are doing from everyday [snorts] life and make sure that these uh things becoming your process that you understand how it works that you can bring more people into your team and they can do from day one. Okay, probably day two uh what's needed, what's requested from them. Next one

that's a tools. Your tools should also become major enough, right? At the beginning, every developer might use whatever he wants, right? And once you grow, it's uh becoming a problem, right? because how you will transfer from one developer to another developer, how other person will understand that how to um let's say connect dots with each other. So you should also work on a proper uh tool set for your company and sometimes even kill particular uh uh tools which are not being used. For example, in our company uh we killed uh notion in favor of

confluence um and uh work on your innovation how you do innovation right at the beginning that something oh idea came to the mind and uh overnight I wrote the code right but uh in a reality in a businessoriented um company right idea should go through some valid ation should uh go through some ideiation, right? And uh you might have a subject matter experts involved and so on and so forth. So you should also work on how you innovate to make that sustainable.

All right. [snorts] So quick check on uh the left side you can see some phrases of hackers, right? Please count uh plus one if you feel that you more on the left side. Right? So for example, if you believe that it works, ship it more closer to you right now. That's plus one for you. Okay? If you believe that everyone contributes closer to you, another plus one. Okay. So next one. Documentation slows us down.

Access is temporary. I will clean it up later. Telegram message equals approval. Telegram or Slack or whatever. Uh security is everyone jobs. So it's fine. Right now let's uh let's let's count who has uh six score. Six. Okay. No one. Five. Wow. I am impressed. Okay. Four. I also impressed. Three. [laughter] Okay. Probably one person. Okay. Two.

All right. And one. [laughter] Good. Okay. So, everyone else I assume just too shy enough, right? just don't want to acknowledge that yes it's indeed six. All right. Um so here you might have uh see some particular terms which you might you you should become professional of on your way for to maturity right at the beginning it might look like a very alienated words for you but indeed you that should become you know part of your DNA something like vendor management right how you on boarding partners how

you on boarding new vendors into your company data protection and privacy very serious thing once you have a billions and billions of dollars going through uh your uh your startup and you indeed working with people data right uh security incident response plan the same right it's better to be prepared ahead of a time while doing that on on a hawk um then I don't know risk assessment risk management right the same type of policy acknowledgement and so on and so forth. So we went through all these uh all these things and uh yeah uh on the path to maturity

it's u it's necessary to see to learn all of that. All right. So as you might lesson number one as you probably already understand that the key point for maturity that's a culture right culture is very very important uh once you grow you will feel it on a uh on your fingers what that's really means but what uh also means that culture u defined by uh your founders right and early employees and uh once you grow changing a c culture becoming

exponentially harder. So please please pay attention to that and if you feel that your company is growing and something not going right uh it's probably do that change that fix that right now rather than fix that later it will be much more harder right so key point here that leadership define culture and you should do understand what's your actually culture means it might be I don't know as in our case uh we still doing hackathons Okay, we have a per around eight hackathons but we put a corresponding processes around that to do that in the right way in a

manageable way. All right, next one. Very very important. That's a ownership must be explicit not implied. Right? When you start everyone responsible but once you grow it means that nobody is responsible. Nobody uh everybody kind of mentally uh mentally pointing out to another person, oh that's that guy responsible. But no, you should be pretty much clear who is responsible for what, who is doing uh CI/CD, who is doing uh uh code testing and so on and so forth.

Um all right. And uh next like a real uh lesson learned that's uh telegram not only telegram so as you but primary right because in the crypto telegram became the factor standard right but as you may see it's uh hard to manage that in a enterprise way for example you have a secret uh chats secret um groups with your clients with your partners and then somebody quit your company and you have to manually delete that person from all of those

those groups and the same with on boarding right somebody coming in how to bring that person into all these telegrams telegram groups so we together with synapse uh build a b telegram bot which made us compatible with Identity management in our case that's uh octa we are using octa all right and probably Ivan yeah yeah yeah that would be me hello hello hello even here so I'm going to talk about policies but not configuration policies but the documents that we usually go next next yes yes to all apply all

goodbye and haven't read them at all. So it was a bit different because uh in order to do them you need to have highest management buy in from them to read the policy policy owners to understand them to know what they're putting inside and then but let's first talk about the policies. So it's actually a document high level document where we actually say what do we want to do and why do we want to do whatever we want to do. And now once we have that done, >> can I jump in quickly >> please?

>> So policies is like a smart contracts uh but for your company. >> Good. Yes. So we need to have policies in place. We need to align with the policies and not only if we don't have them documented and followed it actually means we don't we don't know this we don't have even the structure within the the company. Next slide please. And not only the policies but we also need to have additional documents which are guidelines procedure that says who [snorts] does what and in which way. So these are also the the the the really important thing that we need to have it because we

need to write it down and we need to document it. And uh the thing is where we think we had advantage on compared to other companies is that we had a knowledge management team. So knowledge management team was able to uh gather all of this information, gather all of this data that we have and manage it properly. So it was much easier and faster for us to move during the the certification itself. So how did we actually did it? So we map the current state then we educated the people raise awareness what do we need what they actually need to do of course there is a push back always why do I need to do the papers I like to do what I'm doing I

don't want to do that but okay at the end with the buyin from the highest management this was overridden at the end and so we had a knowledge management team who supported in all of this we enforced it and right now we are going to the sock to type two where all of this is continuously documented. I think that's it. Okay. Sorry, Rox is next. Sorry, Rox. >> Thank you everyone. All right. Compliance accelerates maturity when done right. Very bold statement. The first thing we need to understand is what is compliance? Compliance is the adherence to laws, regulations, your

contractual obligations to your clients or as a service provider. The second step is to understand what compliancy is applicable to me from jurisdictional regulations to jurisdictional uh legislations and to obviously your contractual obligations. So the first step there when you start all of that and you understand that is we need to look at automation. Automation to scale we've got to have that at the back of our head. So while we doing all of this we need to understand okay what do we need to automate? What are the repetitive tasks?

So when you look at compliance and and they say it reveals invisible weaknesses, it just ties into risk management because when you know what your compliancy uh applicability is, then you set parameters and when you set parameters, you are able to identify the risks associated or the as they say here the failures before they actually happen. Um the second part is and this is a mythbuster. So when I go into a lot of companies, I ask them who's in charge or or who's responsible for security and the question that I or the feedback that I get is the head of security or the CIO or the CISO. But that is not correct.

Security is a shared responsibility. So we do it every it's an inclusive um it's an inclusive game changer basically in the company. So every single person in that company uh basically um contributes to security and then we talk about build continuous accountability. So it takes you from reactive to proactive. So now you're not firefighting, you're fireproofing um because you're able to identify risks before they happen. You are a uh able to identify incidents before they occur.

And that is what compliancy is and that's how it accelerates your maturity. Next slide. Um I right the auditor is not your enemy. So I use many caps and one is an auditor's cap and I hopefully not a scary looking person. So what the auditor does is it takes your intent which is your policies and the controls that you've implemented. So basically what you've operationalized and we as auditors validate that your controls are what they are. So when it says that they validate what actually works, it takes your existing controls that you've implemented um that's on paper and looks at it in a practical environment.

So they say accelerate maturity by forcing clarity, accountability and continuous improvement across teams. just means that now everybody's accountable. We've got responsible people in each area. So it is a I I would say a familyorientated um mission in terms of compliancy and that ties into your governance risk and compliance. >> Thank you. All right. probably I will skip a little bit payoff just in sake of a time but uh yeah we are measuring more and more and hopefully from year to year it will

become uh so what what's key takeaways first of all compliance is not bureaucracy right if you think that is bureaucracy that means that yeah you should take a look more more closely uh culture shift is the hardest I hope that we explained that that's really culture that that's a key point there and uh then defy actually compatible with enterprise uh standards they not contradict they're compatible right and that from our perspective lead to sustainable innovation all right uh any questions

test. Hi, wonderful presentation. Thank you. Uh you mentioned you're moving from uh notion to Atlassian as an example of uh of different software. I will call them like web two in this in this example. What would be the examples of web three softwares that you had to move in order to in order to comply with this sort of standards? >> Sorry, what what sort of software in web three? So like the CI/CD processes or monitoring infrastructure. Do you have examples of web three uh tools that you had to move in order to achieve these kind of standards? >> Uh from web three web three to be honest I don't remember that we removed something but we very very picky to on board new or do you remember somebody >> hypernative? Oh yes yes yes. Okay. Yeah.

Thank you. One more question. >> So what kind of advantages uh does it really give you to go through all this uh painful uh stress it is to get to be compliant and uh if you enjoy that are you going to the maximum pain and getting Dora as well? >> Dora compliance. >> Yeah. Um yes, a very good um uh very good topic, Dora. Um yes, that is something in the future, but not at the moment in terms of what the applicability is um in the market. Um in terms of um continual improvement and

and what we do, yes, they do enjoy it. The company has 1 in has embraced compliancy. Um it's not a oneandone. Um it's continual improvement. We've transferred business knowledge across to the whole team. So it's everybody getting involved in it. So yeah, I think you guys are enjoying the journey. >> I do. Thank you. >> Yeah, thank you. Any other questions? >> One more. >> Okay. Uh well, thank you for the talk. I I think uh to founders and a lot of early teams uh we obviously know this is important and nice to have but the

question is uh when and how much money we need to spend on it and especially if clients are not asking for it, partner not asking for it and government is not asking for it then uh how much money do we spend on this and why and when? >> Yeah. Right. >> So, it's not about um you you can't just put a number on it. Um your your auditor's cost to get you validated. Yes, there's a set cost, but when it comes to implementation, it depends on the uh size of your organization, the complexity of your platforms, um the people, the processes, the technology.

So, it's all dependent yes. On your maturity posture. So, at Zero Shadow, we meet you at your current state and we take you from there. We don't just say it's a blank slate or we use um a paintbrush across every client. It's dependent on the client's organization. So if you want to just come and chat to us. >> Yeah, just to add if you're interested in numbers. So if you want just to have a check market ISO and so 2, yes, you can do it like really really cheap. But that will bring you like literally nothing. It will give you just these badges and every next let's say audit major audit

can reveal that it's oh so that's a just that just a how to say just a picture okay so in our particular case let's say if you would want just check marks it's it's small amount but we spent I would say pretty much big amount of money like a six figureure uh for adopting you know for bringing required systems to bringing required integrations to bring required companies as a partners and so on and so forth. So that's again that's that depends on your appetite.

[laughter] >> Uh actually you can spend all your money for certification and you can always upgrade your certification. you can you can spend all of your profit and you can still find a few more holes that you can fill. So the budget is not there. It's important that you mature so you have a team that knows what is doing that is patching what needs to be patched that is compliant and that's it basically. >> Thank you. Thank you very much. I think we have a really >> Thank you. Thank you.

>> short break and then we will start with the lightning session. Thank you very much. >> Thanks. >> Thank you. [laughter] Thank you.

[music] >> [music] [music] [music]

[music] [music] >> All right. Hello, everyone. All right. All right. So, our Steam MC is not here. So, I'm just going to go ahead and kick us off. This is the start of our five minute lightning round. Um, okay. There we go. Now the music's gone. All right. So, we'll simmer down and get started. Uh, five minute talk. So, timer hasn't started yet, but it will soon. Uh, so it's going to be a quick one. Okay. So, this is a general topic just a collection of thoughts that I've had over the industry on uh how we're going to meet institutional adoption in the industry in terms of security leadership, what security leaders in the space should be thinking about. If you're a protocol lead or you work with or rather a

security lead at a protocol or a CISO or just someone who happen to have been given the security hat at your company because they haven't figured out a formal title yet. These are generally things to keep in mind that kind of differentiate I would say people that are good at security, security researchers from people that are actually like good security leaders and actually know how to take on a lot of the additional responsibilities that implies. Um so these are all very just simple three points fit into five minutes. first one um because I worked at a security vendor for about four years and then I actually worked at a different security vendor uh before my current job at turnkey where I do solution engineering um we do notice that like I would say in this industry especially when you're getting started there's a big focus on like working with

external vendors on security audits on setting up a bug bount platform with people like Immunifi maybe even getting monitoring software which are all good things and these are very important things to spend money on uh but I've often seen teams sometimes skip the step of actually building up internal security proess and building and you know paying for both internal security personnel hiring a security lead or security engineer security researcher at some point. Um, sometimes their CTO or a specific security or specific software engineer will take on those responsibilities initially, but eventually you need to start spending internally, maybe also building internal tooling, spending a lot of internal time on bug fixes, maybe also assigning time from your for your software engineers to do uh bug hunting rather than just

coding the whole time. Um, and then generally just looking out and thinking about like okay, what kind of return on investment are we getting for security spend? You know, I've seen people spend uh buy five audits on the same codebase and have them run in parallel and then you basically paid five different auditors to find mostly the same bugs all simultaneously. So start thinking about like what are you actually getting for the money that you're spending so you can do it more effectively. Uh maybe start to evaluate some of your auditors against one another if they are looking at similar scopes. Think about who's most effective. I think what's really effective is starting out with some, you know, very cheap security research auditors, uh, that you have a very productive relationship with to find a lot of early security issues in your codebase as well as working with your

internal security team and then bring in a really like brand name, uh, security firm like Open Zeppelin, like Trail of Bits, Spirit Bit, others uh, to actually do your final audit uh, who can hopefully find the very obscure stuff that your original team could not find. um because a lot of the like very simple stuff has already been found and it's not going to like uh detract and distract them. Uh second, I think what differentiates good security leads is that you're not just focused on your internal security. You're actually having external conversations. You're talking to your customers. You're talking to your integr the people that are integrating with you. You're talking to ecosystems. If you're deploying on a chain, you're talking to other people building on that same chain. If you're going multi-chain, you're talking to node operators, bridge operators. uh ideally you are even communicating with

uh security uh ecosystems such as uh seal 911, BSSC, web 2 and web 3 security groups and learning about like active threat landscapes. And I think the most important aspect of this is that you know who to reach out to in like high-risisk situations where you're like okay we got to like you know there's some funds that have been stolen. We need to move quickly to see if we can freeze them. We need to contact Zero Shadow. We need to contact Seal. We need to contact these exchanges, these bridge operators. If you have those pre-existing relationships or you have a relationship with someone who at least knows how to reach out to them and is trusted, you're not going through an email or a form. You're you're directly contacting someone you have a prior work relationship with. That is going to greatly accelerate your speed and being

able to resolve an incident. Um, so I think this really differentiates a good security researcher who can sit in in a cubicle or in, you know, uh, just anywhere in the world and find bugs, but if you can't actually reach out and find the people that are going to help resolve those bugs, that's not going to necessarily uh, make you a good security leader. A good security leader is someone that can actually go out and communicate with these people and establish these relationships. Uh and then the third thing is like when it comes to actually showcasing security and this is probably the most important part for uh institutional adoption is that you're showing substance and not just security theater. Now security theater maybe works for initial conversations. You can say hey we got these certifications we've gotten all these audits etc. That doesn't mean your

current security state is good. You know someone can do an audit of your codebase a year ago. That doesn't mean today's codebase is actually going to be safe. Um but if you're showing like hey this is the deployment process that we do this is the way that we have uh separated our access control. you can speak to it intelligently beyond just like maybe ranting off what ISO 27001 is telling you you should do or websock should do which are still good certifications to have don't get me wrong but can you actually establish what your security practices look like can you make maybe even give advice uh to the integration partners you're working with and actually tell them what their security model should be consider where you fit in their security model um and then can you like align those controls do monitoring and actually like

maybe showcase things have an incident page uh and of course if you find yourself in incident, you can actually uh communicate that effectively and talk to a lot of different teams, have very detailed postmortems, have very detailed communications with all the teams that depend on you and showcase that like you know even in a case where your security might have failed in some sense, you show a very robust process and how you deal with incidents. Um so the final quote I'll leave you with is institutions don't just adopt technology, they work with leadership they can trust. Most security le leaders out there in web two, they don't know how to evaluate good security in web 3. But if you sit down in front of them and you speak intelligently about your security model, even if they don't understand all of it, if they understand that you take your job seriously and

that you think about a wide array of threats and that you're protecting against them, that will go a very long way. They will say, "Maybe I don't understand the technology enough to trust it, but I trust you because you're building the technology and you're securing it." So keep that in mind. All right. and welcome a chief. [applause] >> Thank you, Michael. Sorry to be late. Um well, as a session chair, uh I'm I'm late. Apologies for that. Uh but yeah, as you guys know, so the this is a series of uh lightning talks meant to be 5 minutes. And just to be fair to all the speakers, you know, I'm going to try my best. I'll be

sitting right here. Um, and when the speaker, you have a minute left. I'll just, uh, raise hands and then please try to finish on time. So, um, yeah. Uh, we have a long list of lightning talks. All very interesting ones. The next one is, uh, we're going to see if we can switch it. Um, do we have Odicius here? >> Oh, he hasn't arrived. Good. So uh so that's that's a good opportunity for us to switch uh speakers. So we're going to have John Tumman from Sera um talking about summary of equivalence checker and AI.

>> Hello. Oh wow, look at that. Uh okay. Hi everyone. Um I will uh finish within five minutes or else Rajie is going to tackle me I think he said. Uh so this is a uh talk about verifying LM code transformations using uh formal verification and equivalence checking. Um this is a very much a bridge version of a workshop I'm going to be giving tomorrow that's going to be 60 minutes long instead of five minutes long. So a lot of details I'm glossing over here will be uh expounded upon in that one. This is really just to give you a high level overview. So uh a quick digression before I start talking about like all the technology here is that at Sertora we have this uh Sertora prover which is our flagship technology um and it allows us to verify smart contracts and

solidity but crucially it relies on static analyses of storage of memory and it uses this to optimize representations and all of that. Um and so a frequently abused feature of solidity is inline assembly and this is uh frequently causing us issues with these analyses. Our analyses work on most bite code, but if you do something particularly egregious or tricky, we end up not working so well. And so to give you an example about what I'm talking about, this is a example from Solotti. Uh it's heavily optimized. It's cache efficient. It is overwriting the free pointer in ways that uh no one uh they really shouldn't be. Um and it's, you know, extremely galaxy brain. Um from the name safe transfer from we have some idea about what it's doing, but really understanding this is hard. And I'm not

trying to pick on Solotti in particular. This code is actually quite brilliant. Um, but it is representative of a lot of different DeFi code these days. Um, it actually kills these static analyses like I said and also it's not hard. It's not super easy to audit either. So that's the motivation. Can we automatically generate equivalent implementations for auditing, code review, analysis, whatever. So there are two parts of this automatically generate and equivalent. And I'm going to focus on this first part here automatically generate. And because it's the year of our lord 2025, this is going to be AI powered. Right? So we take some complex code, feed it into some LLM, and say, "Please rewrite this. Please make sure it's right." Uh, and out comes some nice higher level solidity code that's easy

to audit, analyze, whatever. So is it this simple? Look at our nice little system diagram. Is it really this simple? Well, again, when it comes to AI powered, you of course get AI powered mistakes. So this is actually a rewrite uh between the original safe transfer from and a rewrite that was proposed by Claude and it looks really really close and in fact it is really really close but they are not actually equivalent and it's due to this uh very u nice looking AID code here and this is not super surprising because these LLMs tell us very often that they can make mistakes.

So what we actually do is we take uh one of these solidity files, we feed it into with this prompt to the LLM outcome a simplified version. We take the original and then feed it into this tool called Concord which formally verifies whether two smart contracts are equivalent at all possible inputs. If it is, we give it back to the user. If not, we get an explanation which we feed back into the LLM. And this whole process is what we call concordance. Now we need to focus on the second part of this which is equivalent. And so the intuitive definition I'm going to give is that two programs are equivalent if they do the same thing on the same inputs. Right? So we have input one feed into programs P1 and P2 outcomes the same output. So that is a good starting point. But a more

precise definition would be something like an external actor should never be able to tell the difference between two equivalent implementations. And I'm really gesturing towards side effects here. Right? So what are those side effects? changing storage, emitting a log event, uh calling another contract, which is balance transfers, creation, also self-destruct technically, but you know, you're not supposed to use that anymore. Crucially, what it does not include is any local parts of the computation, memory, stack, and why not? Well, we set an external actor, and stack and memory are not uh visible to an external actor once the contract ends. And so, uh we do not consider them to be part of the side effects of uh the execution. We also exclude gas. It's very important, but if we insisted on

equivalent gas, we would essentially be insisting on equivalent implementations. So this is our formal definition of equivalence. I'm not going to go super deep into detail here about it, but come to the uh workshop if you're interested. So next we have to talk about how we formally verify this equivalence. Uh we use uh stora. we uh need to uh express equivalence as a mathematical formula uh that can then be checked by the uh con uh excuse me the provers's symbolic reasoning uh roughly we encode equivalence as equality of side effects and equality of return and then we verify this with the sort prover. So we take this diagram we saw before and we can then actually treat it as uh these functions as returning output and then

their storage logs calls etc. And then we can create this formula and then check it with a tour prover. I've glossed over a lot namely how any of this actually works. Um you can look at the Concord tech report if you'd like or come to the workshop. So this has been successful. In fact using Concord we found a uh Viper compiler bug with optimizations turned on and turned off. Um, so this is actually useful outside of uh the rewriting workflow that I've uh described so far. So one last thing I'm going to speed through is that we output this explanation. Um, we get this by analyzing the counter example that was given by the solver and then uh we use that to create a highle human readable

version sort of human readable. So for example this one this this is different because well uh all the details here that you need are are here. Um the difference is actually here. This happens if the call ei contract that you did the transfer from two is uh returns two which is not a valid encoding of a boolean which changes the revert behavior. The original uh returns with a transfer from failed hash. The other one returns with an empty buffer because ABI decode. Uh it proposes this fix and so on. And I'm going to actually just skip right past these. Um, the point is that you can uh use this for all sorts of different rewritings. That's all.

Thanks. >> Awesome. Thank you, John. [applause] And for all this, if you have questions, if you want to know more, please, I mean, the speakers are going to be there today and tomorrow as well. Um, so we're going to go on to the next talk. Uh, do we have Gabriel? >> All right. Um, yeah, please. So Gabriel from Ensuro is going to be talking about secure governance for DeFi companies and while while he's getting set up so um can I request all the speakers uh light of lightning talks in this session to please make their way forward and maybe sit somewhere close by.

>> You're external. >> Cool. And there is there is uh so you can see your slides your presentation here on the um on a on the monitor here and on this there is also a clock a timer and that counts down. So uh please do stop when it hits zero. >> All right. Yeah. >> Okay. Hi everyone. So we're going to talk about secure governance uh specifically about multi transactions which is um the main part of the governance on on a blockchain based company. Uh I'm the CISO at Ensuro and I'm mentioning this because we are an actual blockchain based company operating for the last over the past four years and we use this a lot. So this is a set of tools that we built. Uh and the the problem we're trying to

solve is uh that blockchain protocols evolve. We have to deploy new smart contracts when a new customer is on boarded. So we have configuration changes, we have permission changes and we have uh fonts being moved around. And um the way that uh the safe UI shows these transactions is hard to review. Uh especially for a nontechnical user, which is the one that we um the ones that are authorizing uh these transactions on our company are not all technical. Uh so our CFO authorizes transaction and he's not technical. Our CTO authorizes transactions and he is technical and he can read this called data and probably figure it out but the CFO can't. Uh so that's the problem we were trying to solve. Uh and the way we do this is uh first of all we defined um

a chain set which is the definition of a multisig transaction that we want to execute and here we say okay this is going to run through this uh specific multisig this is going to be to use a time log and the delay uh defined for that time log uh and this is going what's going to be run right this step this is going to be a a contract function call with these parameters and the parameters are an address which is uh expressed as an address alias and uh an enome in this case and it's expressed as the value in the enome not as a zero or a one or a two or whatever uh index in the enome corresponds. Uh and then and this is probably the the most useful part of it all. Uh we can define test right there in the chain set right there

in the in the multisig transaction definition and these tests are run before sending the transaction to the safe multisig uh for signing. Uh this is the first part and this uh can be created this chain set can be created by a nontechnical user. It it's not very difficult. It's a very simple format. It can be uh created by an intern. It can be created by a junior member of the team or it can be created by an LLM. Uh once we have this uh this is goes on a pull request on a GitHub repo because this is code in the end. uh it goes through a review process and once it's approved there's a workflow in a GitHub actions in our case that creates the safe multisc proposal and that's the only permission that's

that this uh action has uh it's a delegator on the multisync so it can only create transactions but cannot sign them and the one the person that created the changet has no permissions at all on the multisig only our workflow. So this creates a proposal on safe multisig. Uh and of course we were still having the problem that when uh the users the signers were ready to sign this they were seeing this called data especially when there were time log and other uh complex contracts in the middle. Uh so we also created a safe UI app that is integrated into the safe UI that shows this friendly uh definition of the transaction uh which comes from the manifest that we saw before and uh and

from some intermediate artifacts of that and shows uh step by step what's being executed. It shows the TX hash and this is very important because uh on safe there's several ways you can sign the transaction. You can sign an EIP712 uh strct. Uh but that's very difficult for a non-technical user to understand or you can just sign the hash as a text and that's what we are using for signing and a hash is easy to verify to any user right you use your eyeballs and you uh check that the hash you're seeing on your wallet for signing on your hardware wallet for signing and the hash that you are seeing on the UI is the same.

Besides that, we also have uh notifications on our discore internal discore messaging service. Uh and it also shows a hash and it also shows the the detail of the transaction that's going to be executed. This serves more of a as a as a call out. you know, hey, you have this uh proposal, this transaction to sign, but it also works uh as a second or third check because the hash that's being shown here, the safety x hash being shown here is generated independently from what's being shown in the actual safe UI. So, a hacker would have to compromise three different uh parts of code, three different systems uh to compromises. We actually added this after the by bit

hack analyzing how the bybit bit had happened and how we could avoid it uh with our uh tooling. Um so yeah this is kind of it. Uh we just wanted to show these tools. Uh we want to make these tools available. Actually the safe UI app is already open sourced and the rest of the tools for creating the transactions and running the test and all of that. Uh we can make them open if anyone is interested. We just need to put in some work to extract it from you know from our system and open source it and then uh as next steps we're planning on adding uh in browser verifications or even running the test right in the browser. So if you trust the app, you trust uh what you are seeing uh here and then you can deploy the app on IPFS or some static uh

hosting and uh and you can trust it that it doesn't change. Uh maybe ENS support because right now we are using uh an internal address book like a mapping from names to addresses uh using ENS would be really cool. So yeah, here you have my contact information. If if you're interested in this, you can find me out there in a little bit and uh you know contact me here. Thank you. Cool stuff. [applause] Thank you. Our next speaker is uh Benjamin from Verise who's going to be talking about status statically safe proving security with semantic queries.

computer. >> I didn't realize we had >> Okay, thanks everybody. I'm here to talk to you about how to keep our program safe uh statically. So, if anyone here has performed an audit or reviewed code for bugs, they may be familiar with the rather draining experience of the increasing cognitive load that happens as you identify more and more potential issues in your code.

And what I mean by cognitive load here is that as you think about more and more potential attack vectors and more and more potential problems which might lead to a hack, the number of ways in which these potential problems can manifest and the number of things that you need to check grows much more quickly than the number of problems that you identify. So these are all kind of example questions we might ask when we are auditing a program. Uh, for example, if we have a lending protocol, we might wonder, is a health check always called before money is withdrawn. Or if we're interacting with some address and some internal function, we want to be sure that we always know that address has been validated at some point to be something in the protocol and not something that could lead to us getting

exploited by a re-entry. And this leads to a kind of loop that we wind up having to deal with for each function for each property that we are concerned about for each of those functions for each call site of that function. Is it possible that the inputs are going to violate this property? This is going to require eventually just meticulous notekeeping, tracking, being very careful that can transform kind of the fun creative aspect of bug finding into something that is stressful and even errorprone.

And when we approach meticulous uh problems, we often ask ourselves, can I just have a computer do this for me? And so what we'd like to do is take our bug, our idea for an attack, ask the computer, is this bug in my code? Yes. check mark or no, it's not in my code and I'd like to move on. Now, computer is an increasingly vague term these days. We can be using all kinds of different tech stacks to try to identify bugs. Uh we might be using AI. We could fuzz and test in various different scenarios. We can work to apply full for formal verification. Uh we can try to apply some static analysis which is you know ideally sound. And I've tried to map these out here across three

properties that I think are relevant to cognitive load in auditing whether we can ask custom queries right so lots of static analyzers today the kind of most design common design pattern is we have various detectors built in so we might not be able to ask uh our specific question uh automatic detection is important we don't want to just insert more work instead of notekeeping now you have to do a lot of extra maybe theorem proving and we also want to be able to trust our results we don't want false alerts. Uh which means that if we still have to worry about a potential problem, the tool says uh no, that bug isn't present. Can we actually trust that the bug is not present? Can I actually cross that off of my audit to-do list? And I think one notable uh missing point in

the design space here and we can argue about my exact placement of AI or static analysis depending on your your favorite tool is when the robot here is telling us no. So if we want to reduce cognitive load, we need to be able to cross something off of our list. We need to take something out of that inner loop as we're going through our audit and say, okay, I actually don't have to check for this anymore. I don't have to trace through the call stack and check every time. Has this address been validated? Yes, great. No, that propagate it to the next call site. So [snorts] to reduce that, we need something where we can uh perform a query, have it detected automatically, have it tell us no, there is no such instance of this bug, and then we can still sleep at night because

we can trust that there are no false alerts. And the solution, I would pause it, is to leverage static analyzers in a way differently than we have today. So this is an example of a a static detector from auditub where we have a kind of SQL like detection language and the idea here is that we can be very precise. Uh so I'll very quickly bore you with a quote from Dystra that so-called natural language is wonderful for the purpose it was created for but hopelessly inadequate when we have to deal unambiguously with situations of great intricacy which unavoidably arise in such activities as legislation, arbitration, mathematics or programming.

And my point with all of this and what I just want to end on is that being able to precisely and exactly say what we want to find and what we want to not be present in our codebase and then succinctly and automatically have that checked and removed from our code is incredibly important in building trust and reducing the kind of effort and amount of cognitive load that goes into an audit. Thank you. >> Awesome. Thank you, Benjamin. [applause] Our next speaker is uh Jason from Hex who's going to be talking about scale your DeFi research with static analysis.

>> I'm sorry. >> HDMI or USBC? >> Uh let's do uh HTML side. check. Check. Hey guys, uh my name is Jason and I am a glider security researcher at Hex. Today we're going to talk about scaling with static code analysis tools.

So in security research uh we focus on three different modalities. Uh one is bug bounty programs, two is private uh audits and the third is audit contests. In each of these categories researchers are going to review a limited scope of smart contracts to identify as many vulnerabilities as they can. in this research uh it's it's quite excellent for identifying vulnerabilities on a project level. However, it is ineffective and I would argue not scalable when we want to identify vulnerabilities on a blockchain level.

So, we have a problem which is how do we identify vulnerabilities that just not exist in a project but also elsewhere on chain. I believe that static code analysis can help us bridge this gap. Um I would argue that this is a fourth modality of instead of thinking about audit research on a project base, we think about it on a chain base. So what is static code analysis? Uh to sum up, it is the process of querying source code in our case smart contracts to look for code patterns in our case vulnerabilities.

And the way we do this is we write a query uh typically depending on the tool that you use uh that could be Rust or Python. And this query identifies code patterns. It's programmatic so we don't have to do any manual work besides writing the query. And it's also scalable because we could run this query as many times as we want for however long we want. Um there's currently in the ecosystem a list of available tools. uh there's aderan, there's slither and the one I work on a daily basis, glider. And this talk will be covering uh focused on glider.

So with static code analysis tools, we have available to us a library functions that we could use to query for all sorts of things. We could look for functions defined in a contract. We could look for if a contract has been inherited by another contract. We could look for state variables. We could check for global variables. We could look for local variables. We could see where these variables flow to which is called data flow analysis. Uh it's extremely helpful for many vulnerabilities. And in particular with Glider, we could actually run a query against the entire chain of every verified contract. And we have that in our database. And you can

run that as many times as you like, updating the query whenever you want. for new contracts that are deployed on a at any time. So, uh what I want to show next is a demo of a glider query that looks for a very famous and old vulnerability called unis swap v2 spot price manipulation using the get amounts out uh function. This function obviously returns a price that is then used in a swap. And so normally in traditional research uh we would have to go line by line and review and look for this function. Then we have to trace where

this return value of get amount out flows to. Uh this requires significant effort, time and energy on our part. We have to find the contracts that support this that call this that have this sort of code pattern. But with uh glider we will be able to look for this automatically. So uh in this video we're going to show uh this is the glider IDE and right up here we have our glider query which is going to look for instructions. You could think of instructions as a line of code that looks for a a instruction that calls get amounts out. And then we're going to do something called, as I mentioned before,

data flow analysis, where we're going to trace where that value, that return value from get amounts out flows to. And we're going to check to see if it goes into this swap function. I'm going to go ahead and play uh the video, and we're going to run it against the glider IDE, and it's going to scan. Um in this case I have limited the results to a single infected uh vulnerable contract that was found two weeks ago. Uh you know as old as this is uh this um this bug still exists. So uh here we could see that uh the contract was found and that get amounts outflows to the swap function. Um here's all the links. We also have a glider contest

ongoing for a static code analysis query. submit your query and get paid. It's sponsored by Ethereum Foundation and if you guys want to let me talk uh ask questions um I'll be here. Thanks guys. >> Awesome. Thank you Jason. [clears throat] Yeah, please uh go and check out all the tools that uh that are being shown. Um so for the next one next talk is by Gulmo from trail of bits who is going to be talking about mutation testing with slither new way to find high severity issues.

Yes, I think it's >> Well, hello everyone. Uh, thanks for coming. I'm Gizarmmo from Trail of Vitz and today we will talk we were we are going to talk about mutation testing and a way to find bugs that the tests are missing. So we already know that tests improve your code and to quote Alex uh he said that uh if your code is not tested it is broken. So we need a way to

figure out how to test our tests. So normally for a blockchain project or any project in general you will have different kind of tests. Unit testing for example that uh test the behavior of individual functions or you can create unit tests for edge cases for example. Then you have the next step is integration testing where you start um testing the how the different contracts or the different functions interact between themselves and how the whole system works. uh you can create user flows, administrative administrative flows or whatever. Uh we also recommend that projects that have some kind of arithmetic or rounding error that are

prone to rounding errors also implement fast testing to ensure that uh you detect uh those kind of issues. But the big question here is when you have your test suite implemented, how do you measure how effective the testuite is to catch bugs in the real life? So one answer to this would probably be uh coverage. Uh is it a useful metric to know how how much your tests are covering your your code base? But the thing is that uh coverage doesn't really explain or doesn't really show you what uh bugs are being missed in in your in

your codebase. So for that we will be we will be talking about mutation testing. First uh brief description of what mutation mutation testing is. So basically in a normal project you have your codebase you have your test suite and where you run all the tests pass and that's the minimum expected for a project to be safe. Uh in the case of mutation testing, we are going to introduce mutations to the codebase and those mutations can be small bugs that are introduced purposefully like uh on on purpose to change the codebase and see if your test suite actually detects the change and make the test fail. Those

mutations could be comment out the line u replace operators like assignment operators, arithmetic operators or whatever. uh replace conditionals inside uh the if conditional or for loops for example there are a series of many different mutators that you can uh introduce. So for each change that you make to the codebase you basically generate a new mutant and you run the test suite against that mutated codebase.

Of course we can have two possible outcomes. If the tests fail then your test suite is actually detecting that bug that bug and everything is okay. The that modification that mutant was caught by the test suite and you are safe from that particular mutation. The alternative is that the test pass and now you have a problem because you modified your codebase and your test still pass. So that's when you have to start uh investigating and see why the test passed.

Uh this is a very timeconuming process as you know uh mutations are introduced one by one. Uh each file and each um line [snorts] of each file will have to be mutated. So the idea is to automate this and not do it manually of course. So for that we have Slither. Slitter has a tool that's called Slitter Mutate and it's supposed it's meant to be easy to use and it's supposed to be used by every project that has tests. Uh to run Slitter Mutate, you point it to the folder where your contracts are and you specify which test test command are you going to use for running. For example,

we have forge test if you are using foundry. Uh hard hat test if you are using hard hat or whatever custom script you you have to run your tests. So what this will do will start generating mutants running the tests against the mutants and detect if some of those tests uh don't pass with a mutant. Um, basically the output for this tool will be similar to this. For each contract, each file, each mutant that it generates, it will show that it's mutating the contract name. It will show which mutator it is using. Uh, and it will show the previous uh line, the previous code and the new code. Uh, and

it will show you if it got the mutant or not. So for uh big codebase, this will take long time to run. So what we suggest for auditors is that you start at the beginning of the audit to run the mutation test for uh other for normal [snorts] developers to run this once in a while to ensure that your test actually cover everything. Uh to finish we have the help command and the list mutator comment that you can show and this is a blog post that we made about the tool with some real life examples. Thank you very much.

Awesome. Thank you. The next talk is going to be from Mark um from chain security and he's going to be talking about try catch and solidity reviewed. Try to catch this. Good. Yeah. Yeah.

Hello everyone. I So I'm Mark. I'm a blockchain security engineer at chain security and I'm going to give this lightning talk to talk about uh try catch in solidity and speak about some edge cases that we um still see are not understood fully by developers and I mean also by some of some auditors sometimes. So here's a recap of some edge cases. So I hope everyone knows what try catch is. Try catch um can can be used uh to wrap external calls or contract creation. And uh there's three different catch clauses that can be used with it. The error, the panic, and the

like let's call it the low-level uh clutch uh catch clause. Um so the the error clause would be used um on normal reverts with with a reason and condition whereas like panics would happen when like it is for errors that are not supposed to be there in bug-free code such as like arithmetic overflow, invalid array accesses or division by zero and asserts. And uh the low-level fallback is anything any errors that do not match the above two. So uh for example uh decoding the error data of

the error or the panic if this fails would then be caught in the low-level uh fallback uh clause also out of gas and custom errors would uh fall back into that one. Um and let's do a a small quiz, right? Like this is a simple example external call uh into um interface interface I of a function fu with an argument that comes from an internal call and the question is like can this revert right because we use a low-level catch clause this should catch everything right and turns out there's several reasons right first one if the internal call reverts even though we are

inside our our try we will revert. The second one is a bit more uh complicated is if C is an EOA then solidity performs before we enter the like a try try part we perform an X code size check and if this one fails we will revert. Um since uh 8.10 the Xcode size check is is however not done. If we expect some non nonzero return data size which is our third reason right if we don't get the expectant return data size from our external on the call we will also revert

and not catch this. So uh generally we can think about it that everything uh all the reverts in the external call will uh in the the collie will be caught whereas like reverts coming from the caller and and checks introduced by solid that are done before the external call will not be caught. Uh yeah so takeaway also reverts inside try try or catch blocks are not caught as you can see in the above example. Um as I said Xcode size checks and return data size checks are not caught and also

the AI dec code failure on return data uh code. Thank you very much. That was all. I hope you have a great day. [applause] >> Awesome. Thanks Mark. great reminders on the solidity things. So we have uh the next speaker is um Vira from camp network who's going to be talking about EIP7702 empowering EOA's expanding attack surfaces.

And you need to >> allow entire screen >> and I move it. >> Hey uh hi guys. Uh my name is Viraz. I'm a senior smart contract engineer at camp network and today I'm going to be uh discussing extensively about EIP7702 how has it uh you know empowered EOAS and how has it uh sort of also expanded uh attack uh services uh on the other side of things. So u we just start off with a recap of what we have seen in the space in the last few years. So a ton of

statin was introduced to simplify u uh for crypto for different types of users whether retail or other uh DGEN users uh so that we could uh get rid of the approved transactions when you know dealing with ERC20 tokens or uh things around um you know like paying gas in different tokens etc u gasless transactions u and there are like the list goes on uh in terms of how you know we could you know get made the UI more much better than it was before and we chron uh chronologically we started off with these uh three uh you know different EIPs and uh ERC standards that uh you know we've been sort of seeing in the space. So we started off with EIP7 3074 which uh introduced two op codes or

and Ocrol and that allowed uh uh full control like a user to give full authority to the smart contract uh you know to do uh do the executions on its behalf and then there were obviously some security concerns with it because you were relying completely on the uh you know the uh on the contract and if a malicious contract or things like that happen then your uh you know your wallet gets wiped out instantly. Then we had uh ERC 4337 which involved uh off-chain and on-chain components with user ops and a bundler ser bundler to uh basically prepare the transactions using the user ops and then a entry point contact where you you would send the uh user of uh structure the structured transaction and

the entry point would basically execute it on behalf of the user. And uh lastly which is uh you know uh lastly but uh you know which is the most important one is EIP7702 which is you know which we are using right now which came with the Petra upgrade and the idea behind that was uh introducing a new transaction type uh where uh you would allow EOS to attach a new uh delegator and that would do uh you know transactions on your behalf on a transactional basis and so it improved upon what uh 3074 you know came up with. Now we talk about the attack vectors and uh the adoption that uh EIP7702 has seen. So uh in this chart you've seen uh this is the first attack vector which is pretty common which is

again which I spoke about in the previous slide around uh you know just delegating to a malicious contract which is which can still happen because some for example a layman user or a retail user sometimes doesn't verify the delegator that you know that you are basically giving control to and in one click if you don't you know do your u checks and verifications in that sense uh you know like decoding call data and things like that so you can just delegate to a militia his delegator and your uh entire uh you know wallet gets wiped out in one place. The second one is a bit more interesting which is around redelegations where if a user is uh you know is into like you know using different account uh like delegated contracts and they uh you know keep uh

like they redelegate often to different delegator contracts then there can be a case where the storage slots uh differ and again which is which comes down to the previous issue where you don't verify the you know the inter the codes part of uh the delegators and uh the because of the storage slots being different you there can be you face issues when you know doing executions or things like that with these delegators. Now the we have this interesting dune dashboard that was created by winter mute and as of uh yesterday as of 18th November in fact we have seen like there have been more than 5.5 million uh authorizations more than 2100 contracts uh we have seen uh you know more than 12 million addresses who have you know just

used these delegators. Now uh the right chart is a bit more interesting where the orange part uh is around the malicious delegations that have been made which you can see is a lot right so that's is that's the point uh that I was speaking about that you need to be very careful when you know interacting or uh delegating uh to a different uh to a delegator uh yeah and now this is the non-adoption part where uh we have seen that this is a website called 7702 beat which basically states the days since EIP 7702 has in life and these are the wallets or the DAPs that haven't adopted it yet and I believe it's not just and notable people have tweeted about it and I don't I believe that it's not just

about the attack vectors but it's about the narratives that that have been created in the space around memecoins or you know H42 agents and side of things uh things like that to and which also have more business profitability as well and that's why we have seen not seen this but I'm on the bandwagon of people where you know I support it and I believe that everyone should uh support EIP7 7702. So yeah, thanks a lot uh and thanks a lot for listening in and I'll be around and if you want to have a chat around this. Yeah, thank you. [applause] Thank you Vas. Please welcome our next speaker uh Valentin from Diligent Security who is going to be talking about testing ZKVMs for soundness and completeness

bugs. All right. Um yeah. Hi. Uh this is joint work with um my colleagues um Kristoff and Maria from Teov. So um why should we fuzz uh CKVMs? Well, there's essentially there's two main reasons. Um, one of them is, uh, that they're incredibly complex. There's a lot of optimizations people are doing implementing to get them to be even faster. Um, and that of course has a

possibility to introduce bugs. And of course, they will also uh become very critical in the near future for the correctness and security of upcoming blockchains uh, including the Ethereum L1. Um so there are two main um bugs. The the most critical bugs are uh soundness and completeness bugs. And the soundness bugs in simple terms is essentially when a ZKVM uh accepts an invalid execution. And the completeness bugs are essentially kind of a dual uh where uh a ZKVM would reject a valid execution. And as you can imagine, both of these bugs are critical and they could result in catastrophic financial and reputational damage for the teams

building the ZKVMs, but also anybody that's building on top of them, right? Um, and uh, in this talk, I'll give a quick overview of how we use fuzzing to detect those. Um, yeah, fuzzing is a testing technique that's been used uh, widely in industry to find bugs in very complex systems. So, Argus is the first um fuzzer that allows you to detect soundness and completeness bugs in ZKVMs and it already supports uh six different ZKVMs uh and found 11 critical bugs in three of them. Uh so, in particular, it found three uh soundness bugs and eight completeness bugs in these VMs we tested. And we also found uh we also got

some bug bounties for the bugs we found. Um and the whole infrastructure uh builds on um another fuzzer we built um a while ago called circus which is targeting these uh circuit processing systems like uh for instance Circum or Noir and it found also a lot of bugs uh 20 uh soundness and completeness bugs in uh four different systems. And if you want to learn more about this uh fuzzer um check out my uh talk at Defcon last year um or you can also look at the research paper we um published very recently at CCS which is a top uh security conference.

So now let me try to give you a very uh brief overview of uh how Argus uh works. So the first thing um that Argus does is it will generate a rust program uh R with an expected outcome E and uh this is one of the key innovations uh how we generate this uh rust program is is one of the key innovations in in Argus but unfortunately I won't have time to cover this in detail here. Um once we have the program uh we can then um go to the input generator which generates inputs for this program and um with these two um yeah with these two we can then actually run the the program on

the ZKBM. If the ZKVM crashes we um we find a completeness bug. Um they are shown in orange in on this slide. Uh the soundest bugs are shown in red. Um yeah, if the ZKM doesn't crash, we uh get a proof P and we also get an output O. So then we can actually use the ZKVM's verifier to check if the proof uh is valid. Um if the the verifier crashes or if it rejects the the just the proof that was just generated, then that would again be a completeness bug. uh if the provers

um the proof sorry if the verifier accepts the proof uh and the output is different from the one that um we expect then that um constitutes a soundness bug. So now you can already with this very simple um pipeline you can already uh find both soundness and completeness bugs but essentially we we went one step further by introducing uh so-called like adversarial uh ZKVM. So this is the the second key innovation in in Argus. Basically, we we took uh existing ZKVMs and kind of patched it to introduce some subtle faults during the execution that will allow us to generate invalid proofs. So with this adversarial ZKVM,

we can then again generate another output and another proof and we can again invoke the normal verifier um to see if it crashes. If it doesn't crash, we can again check if the the output that we get from from the the adversarial ZKM is different from the expected output in which case we found a soundless bug. And this is actually how we found all three soundless bugs in um that we reported. So uh unfortunately I don't have more time to to go into details but uh please feel free to reach out um to ask yeah uh about more details on on Argus or if you want to uh fuzz your ZKVM uh let me know and talk to me.

Thanks. [applause] Really cool stuff. Thanks Valentin. [clears throat] Our next speaker is uh is Nikesh from Open Zeppelin who is going to be talking about unconstrained machines. >> Okay. Um I'm going to talk about security review of ZISK.

So the agenda is what is ZISK? some security properties, some vulnerabilities you found, some thoughts on tooling. This is going to be very very quick. So if you see something on the slides that I don't cover or you just want to talk to me about something uh about it afterwards, I'll leave my details on the screen. Okay, so what's this? CISK is a ZKVM. It's compatible with 64-bit risk. Importantly, for our point of view, it's optimized for low latency proofs, which is really good if you want real-time proofing. Um, first big win, it's open source. That means it's transparent. No lockins for users. lots of love from open zeppelin because of that. But the one I'm going to highlight at the moment is it's lots of well- encapsulated components which is really useful. So that makes it good for security reviews. Uh quick anatomy of a

ZISK program. So if you start with some program counter at the start and then you execute a bunch of instructions and you get to the end then you have a valid ZISK program. So to make sure we're executing the correct instructions, there's a ROM component that's a whole separate circuit and that's its job is to make sure that every instruction we execute was preloaded as part of the valid instruction. Uh, one of those instructions might access memory. There's a separate component to make sure that you're doing that consistently and making sure you're aligning all the addresses correctly. One of those instructions might use a register. We want to have a separate component to make sure that we're uh uh that we're reading and writing the latest state.

The timestamps have to have a range check, a separate component for that. Once we're sure we're executing the right instruction, we have a separate component to make sure that the execution was done correctly. And as you can see, the pattern here is what we're doing is just breaking it up into all sorts of little components uh to try and handle each part individually. Uh if it turns out the program itself is just too long, then we just break that into a separate component and then just have a sub separate point there. So the intuition here about what ZISK is trying to do is that they've broken this into a bunch of different components. Each of these can be proven independently and therefore the latency goes down because you can do them all in parallel and then you can get like real-time proving and that they're really trying to optimize

for that. From my point of view, the other thing I'm going to say is this also just happens to be really good for security because whenever we're reviewing the system, it has very very clean interfaces and you can like sub them in and out. So it's really easy that way. Uh so I just think it happens to be a good little um it's a very complicated system that is broken into very simple components. So, I think that just makes it uh makes it really useful. Cool. Let me just go through some of the bugs that we found just for the sake of it. Uh some background. If you tried to do a lookup like an exor, you want to validate that a x or b equals c. Keep in mind the prover gets to pick all of these. So, it's our job to make sure

it's consistent. What we do is we construct one of these binary tables where we have all of the possible one byte values of a, all of the possible one byte values of c and b and then the corresponding value of c. And then we just go from least significant bytes to most significant bite one at a time. Just making sure it's all consistent. We have a separate one of those for every single uh up code, every binary up code at least. So the problem here, if we're looking at the less than or equal to up code, uh what they were doing was just checking the high bite, which works in most cases, but if they happen to be equal, the actual answer depends on checking the next most significant bite.

Uh they were missing that particular check. So we just had to recommend doing a a carryover for that. This one's a little complicated comp complicated to explain. I won't go through it in detail just because uh we won't have time. But I might just mention that if you're looking at a 32-bit op code in a 64-bit machine, uh one question that comes up is what do you actually count as the high bite? Should I consider bite number three or bite number seven to be the high bite? It doesn't actually matter as long as you do it consistently. Uh but there was like an inconsistency in two parts of the system and that caused a couple of bugs in this case when you're trying to do that correction. And the last one I'm going to talk about is the carry. If you trying to add let's say a plus b equals

c if you have an overflow in one of the bytes you need to carry the one obviously um some some of the oper operations have a carry some of them don't some of sometimes the carry should start at one sometimes it should start at zero the way this is all handled is with this has initial carry uh flag uh that wasn't constrained so that means that it was always possible to turn the ones into zeros and zeros into ones when you're just doing the initial carry so you get an off by one error there is a slight subtlety with this factor of two, which I won't bother explaining other than just noting that it is still possible, even though there's a slight complication there, it's still possible to turn the zeros into ones and the ones into zeros.

Okay, so a couple of observations. Those first two bugs were like logic bugs. And as it turns out, they were um they have a transpiler where they start with uh with a risk program, turn it into a ZISK program, and then they just transpile those operations. And they weren't using any of the buggy op codes. So that that was like a part of the reason why they didn't detect those. Those are the kinds of things you detect with a the test suite. But uh the under constrain bugs actually hard to detect. They're a bit more subtle. You kind of have to figure them out from either direct reasoning, sat solving or some sort of tooling mechanism. Okay. So this is my last slide. I'll just mention that we did experiments some tooling. Uh we used the Z3 SAT solver. It managed to reproduce some of the findings and also found a

regression bug was kind of interesting. I would love to be able to do that interactively. Maybe it's already possible. Some people have mentioned a couple of these tools. I personally haven't used them. If you have any uh insight into that, please let me know. I'd love to talk about it. The last thing I'm going to say is I was on a panel about four years ago being skeptical of formal verification. Uh mainly because people were talking about it for DeFi and I was claiming it has a bunch of requirements that I don't think DeFi was meeting. But as it turns out, I think it actually does make sense for something like a ZKVM. So I'm actually excited to see that happen. I hope they they will do that soon. Cool. Any questions, please hit me up in Twitter or email. Thank you.

Great. Thanks to all the speakers of uh the lightning session. That's the end of this session and we go on to the next one which is about vulnerabilities. So please stick around for that one. Sorry. Sorry. Hello everyone. Um for the next talk

we'll have OAX Monsoon talking about adversarial ERC 4626 how vault share manipulation still bypasses listing screens in 2025. Very interesting talk. >> Welcome. Hello. Thanks. Uh hi. I'm a security researcher at Open Zeppelin and uh I'm going to talk about uh wallshare manipulation and er in ERC 4626 walls. Well, this vulnerability has existed for a long time. We've probably known about it for like 4 years since the walls uh were first proposed.

And uh we've seen a lot of hacks because of this in the past and um somehow uh they have gone down in number but they aren't they haven't been completely eradicated yet. And so this presentation is about um the hacks that still happened this year and uh what we can learn from them and prevent them for from happening in the future. All right. So let's talk about the vault. So ERC 4626 uh was uh proposed like four years ago in 2021.

Uh did the screen go blank? Okay, it's fine. Okay, it went blank again. I should probably not step on the wire. I'm sorry. So yeah, they were proposed four years ago. I think most of the people in the room are probably familiar with them. Um they are basically for yield bearing tokens. Uh you could deposit assets. Those assets are put to use in some other protocol. They earn earn yield and for that uh you're given like share tokens which you can always redeem uh for the underlying assets and um they are okay. I think all right it's back again. So uh it's a

very widely adopted standard in D5 now. Um, can you please see what's happening? I don't know what's causing the issue now. All right. So, I I'll continue um while we see what the problem is. Um, so these vault basically maintain an internal exchange rate between the amount of underlying assets and the shares that the vault has minted. So, Um let me try to move to the next slide.

So uh the biggest the I I'd say the elephant in the room uh with the RC4626 WS is the exchange rate. uh because this exchange rate how it's calculated usually depends like uh it it's it's it's what usually on it's the thing on which basically uh it depends whether the wault is secure or not and whether the integrations uh in other protocols are secure or not. Any protocol that uses uh these wall tokens may be at risk if the exchange rate can be manipulated.

So um should I continue or should I stop the I should go. Okay. All right. All right. So usually this exchange rate is calculated u by dividing the total number of assets that the wault has been given to or deposited by the total number of shares. But um there are two ways to actually get the assets into the wault. One is by using the deposit or mint functions. The other you can you can just donate assets to the vault by by using like an ERC20 transfer. So that can increase the exchange rate artificially and which may not be good for

integrating protocols. So integrating protocols usually to get uh to see like how much the shares are worth uh call the um convert to assets function. say supply uh a number of shares to the function and that gives you the number of assets. So imagine let's say a uh lending protocol is using wra st and it wants to know like how much is is a wrapped staked ETH worth in stake. So they can just call the convert to asset functions and then they'll get uh the amount of stake deed then they can use let's say a chain link oracle that is that supplies them the price of stdeed to USD and then you know they can uh basically use the functions of the

lending protocol determine how much collateral how much health factor and uh whatever else is required. So, does this mean that using ERC 4626 volts in your protocols means that you're wrecked? Um, not necessarily. So, let's see um what it really depends on. So, there I'd say there are a few preconditions for any kind of hack in integrating protocols to happen.

First is that the convert to assets function or any other function that provides the exchange rate of a of a ER64626 vault is used. Secondly, usually you have to take the vault to a really low share supplier uh because at that point uh any kind of donation you do just gets amplified because there aren't a lot of shares in in the vault and the amount of assets become very large. So and the third thing is the integrating vault um doesn't do any sanity checks on the exchange rate. So uh if a really large price or a really low price is supplied, it just uses that

uh as the correct correct price and that uh is what becomes problematic. All right. So let's quickly go to go through the two hacks that happened this year uh due to wallshare manipulation. The first is the Venus hack on ZK sync era blockchain. Um in this one basically um so for context uh Venus is a folk of um compound V2 uh which is a lending pro protocol um which okay um you do that uh I'll I'll just continue with it. So is it uh so Venus

is a fork of compound V2. The assay that was used here that was vulnerable was Rabb USDM uh which is just an ERC26 ERC 4626 vault where okay all good um where USDM is the underlying asset and WSDM is is the is the share token. So in this case the vault offered no production against donations and um the exchange rate uh uh the convert to assets function was used for the exchange rate in in Venus and it was combined with the chain link oracle which provided USDM price in USD.

All right. So the attacker first took a flash loan of a lot of wheat and then they opened two types of position. First they deposited uh uh VET and borrowed all the W USDM from the market and then they opened another position where they deposited W some amount of WSDM. So they had from another account. So they had two positions. One in which they borrowed WSDM and one in which they lent WSDM. Then they took the uh remaining WSDM redeemed it for USDM. Uh so that took the vault supply very low and then they donated the redeemed USDM uh to inflate

the exchange rate from 1.07 to 1.7. So after this uh they were able to liquidate the the position in which they borrowed WSDM and in the other position where they had provided it as collateral they were able to borrow other assets. So u this is how they pro profited and uh then there were other things because the vault had a really high exchange rate. Then uh they were also able to use that to arbitrage over some AMMs where they bought WSDM redeemed it and then uh dumb the USDM.

So uh this is a flowchart on how it happened. If you see on point number two right here where the price is returned uh that is 1.7 USDM that's the problem. It should have been uh 1.07 and that is what u ended in the hack. The sec the second example is uh the resupply hack. uh in this uh resupply is um CDP vault that issues a token against collateral and uh the asset is uh the asset that was used as collateral which was uh ERC 462 ERC 4626 vault which was empty. Now this must ring some bells in if there

are any security researchers here due to the first deposit bug that everyone is familiar familiar with but this is not what what happened here anyway. So it was an empty vault and um the convert to assets function was used again. So resupply uh listed uh CRV USD if that's the as I think that's the name of the vault token as collateral and it was an empty wault. So what uh the hacker did was they donated u about 2,000 E18 worth of um tokens

uh to the vault and then they uh called deposit function and maintained one way of shares and they took the exchange rate to 2 E18 and um uh because the exchange rate was so much um um the so another thing is the exchange rate was very high now at this point and the vault was empty now they went to so this is the code if you'd see uh they tried to use some dead shares here which was um I think the value was thousand but it did not really make much of a difference because they donated a lot of assets so let's come to resupply code

quickly so if You could see the price was fetched uh using the convert to assets function by passing in 1 E18. 18 was the number of decimals. Now the hacker was already able to manipulate the price to 2 E18 which after multiplying them u returned like 2 E36 and the exchange rate which was calculated here this uh resulted in zero. Uh so and this exchange rate was used in the issolvent function uh right here.

So the LTV became zero uh of the hacker and uh this check passed and so they could supply any small amount of uh collateral and they were able to mint till the maximum supply for the collateral which was like 10 million USD. So this is how the hack happened also due to Walsh share manipulation. So yeah, so what was missed in the listing checks of these collateral assets? Well, they just checked if the if there was a price oracle uh and which was there but it was exploitable.

this they checked whether the there was deep dex liquidity but that didn't really matter and there was no check how much initial liquidity there was or how much the price per share can grow in any amount fixed amount of time. So all these checks were lacking and they had like no supply and debt caps and in this in the case of resupply fire the there was a debt cap but it was really high for an empty vault. So what did we learn from uh both these hacks?

So there are two parts of it like for vault creators who are creating the uh ERC 4626 vaults and uh then therefore uh learnings for integrators. So for vault creators uh Oiler actually wrote a really phenomenal blog on this um last year which is called like exchange rate manipulations in ERC 4626. So please go through it. Uh I'll cover some of the points in very brief uh detail. So first you could just use an initial deposit where uh if you're listing a vault or um if you're deploying a vault just dep uh just call it deposit or mint function and make

sure um you have some initial liquidity. So a lot of first deposit bugs and vulture manipulation cannot happen due to low low supply of shares. You could also use virtual deposit where instead of depositing something just you add a certain amount to uh the total assets. Let's say whenever you're calculating the exchange rate you add like a,000 or one E6 one E6 to to the total assets. That also helps a lot. It wouldn't actually prevent it but it's still a good measure. You could do internal asset balance tracking. So instead of calling the balance of function, you track the amount of balance that keeps on increasing whenever deposit or mint happens or

whenever the total assets grow due to wherever you've invested it. Um you could also average the share price. So instead of the share price increasing uh at once whenever increase happen it's averaged out through a few hours. That would also make it more difficult to manipulate it, manipulate the share price. And you could also track the exchange rates explicitly like whatever the exchange rate is. It's if it's 1.07, you just track that. You don't track the assets or balances. And uh then you could also add to app to it and whatever you want. So

uh [sighs] all right. And you can also discard stealth donations stealth donations which is what happens u due to rounding uh due to rounding when like if you're trying to deposit three way of something but you only get tokens for two way of something and one way just gets added to added to the assets. So um you could you could discard that by keeping an explicit track of it. All right. What are the learnings for integrators? Well, um firstly, do not use ERC 46 4626 price per share uh uh these tokens um as the uh borrowable asset or base asset uh without caps like supply like

very very explicit caps and um try to use them as collateral until well until they mature. uh have dead ceilings, have um caps for the price that you want. Um uh when you are listing require some initial TVL and uh initial supply um because with empty vaults they are really really easy to manipulate. And uh another thing you could do is uh as the integrator you could provide some liquidity to the vault itself and you can burn that or put that into your treasury. So you're always sure that um the share amount or the total supply

cannot go down by a lot uh like in dangerous territories because you are also you also hold some shares. Another really good uh um defense is to use a correlated asset price oracle uh where you supply how much you expect the vault price to grow and it keeps a track of it and um every time the price is uh the convert to assets function is called in this case it's latest round data but it could just be convert to assets. It just tracks how much time has passed and how much the yearly growth we expect and it doesn't let the price to grow grow more than that because um if

the max ratio is less than the current ratio it just swaps it around. So all right, let's move quickly. Um could also use quill switches like uh uh this is like a monitoring recommendation. Uh if the price per share has moved by a lot or or the liquidity shrinks by a lot um you could just pause the market. Um there's another thing you could do um before calling the convert to assets function. And you can check the total supply of the vault and uh you can have a threshold and if the total supply is below the threshold you can just revert um and wait till the time the vault has more more shares.

You can use market price oracles if they're present. Um, with poodle oracles, it's it's it's really easier to get price for a whole lot of newer or tail tail end assets is uh but it's not always possible. And most importantly, have a listing checklist. Uh, this is for all the integrators and curators. Everyone have a listing checklist. have a certain um things that you check for every asset you um list as a collateral or or you make a market for a base asset. have it out, have all all the check all of these things. Uh because so this is an example. Um we built this

listing checklist for compound when uh we were used to work with compound. And um you could you could take this for uh see this was for inspiration. And uh so this is something that we explicitly checked every time when we were listing an asset on compound whether like um the if and a vault token is used whether it's uh share price is manipulable or not. So don't depend on audits. So don't say that this token has already been audited so we don't need to see it. So every time what we used to do even if it had audits we always tried to see if in some way we can manipulate uh the share price by donating by still

donating by doing all all all sorts of things by you by taking a flash loan out of the vault. So you just need to be very vigilant and um yeah so ERC 4626 is not broken um but integrations are and uh if you integrate these tokens well even and if they're made well even if they aren't like even if their share price is a bit manipulable there are way many def there are a lot of defenses that you can use.

So yeah, that's about it, man. Um, all right. Uh, does anyone have any question? I think we have time for one. >> No, >> I do have a question. >> Yeah, >> how do you how do you ensure over time that the share rate is not inflated? Because uh usually inflation happens right when a bot is deployed uh when it has zero shares. But what if everyone withdraws all of their funds and it becomes empty again in the future? Have you thought about that?

>> Right. So, uh if I go back, so if you as a uh vault deployer um use some initial deposit, right? So you can always make sure that it never goes back to zero, right? And that yeah, that that solves the problem. >> All right. Um thank you guys. That's it. That's my time. Um, [applause] all right. Uh, for the next talk, we have Anup uh, talking to us about when

trust gets tricky, the state of TE security today. What is this? this one. Yeah, there you go.

All right. Uh, everyone's just coming in, I guess. Okay, we can start. Um, hi everyone. Um, I'm Anup. Um, security engineer at Igon Labs. Um, one of the main reasons I wanted to start this talk was to sort of give a like sort of information um data that we found when as part of igen cloud we started looking into tees very seriously and um you know there's a lot of information out there there's a lot of uh very interesting conflicting talks and uh predispositions about the uh hardware and what does it mean? So I

wanted to sort of explain this in a way that either security folks or app developers would sort of need to take things into consideration when you wanted to deploy your app um on a TE and on any of the offerings that you know you might have been hearing throughout the conference here. Um so what primarily we'll go through is primarily the two intended audience which is as an app developer how does an attestation life cycle look like and you know you'll find many many flowcharts of what an attestation flow looks like from hardware TPM to all the way to what it

is but I'll show an example of a attestation from GCP primarily um because that was the easiest I could get to work without having to you know contact Azure or others to get things working. Uh the other one is at the end I'll sort of go through how how do you realistically sort of understand a trust model and assumptions and so that that translates as a security person if you're looking at it like oh I can attack something like this versus an app developer like okay I can take this much trust away from by deploying it on a TE but I do have to consider these other

mechanisms as So I um quick intro this does not do TE's justice but I'll just do a quick intro. Trusted execution environments you can think of it like um extension slash a protected region from the processor and whose whole job is to provide confidentiality integrity and the one of the most important parts the attestation. So confidentiality um only the code inside the TE can read the TE's memory. neither the hypervisor or you know if you if you know about the ring trust model ring zero ring one ring

two um even the hypervisor who would be involved in scheduling your you know VM and other things would not be able to read once it's started and you know that's the model that they want to go for integrity again nothing outside some other process even the h um CPU hypervisor and the other things cannot modify this like only within the DE and that's what they attestation. This is where app developers and everyone else comes into play, which is you can get to a test very specific and interesting things about your app, the environment you're in, um the firmware you want to comply, the many other interesting parts. you'll see an example um benefits again what

you get away from running a normal process where there's already segmentation from the CPU versus running in a hypervisor [clears throat] which is you don't you can remove a lot of the trust um away from the hardware manufacturer like even almost the cloud itself um there's a paper demystifying TDX by IBM research where they try to take the trust away from say GCP like Google cloud itself to sort of uh help people understand like just with pure intel you're able to verify a lot of the things and you know it's one of uh the backbones for modern computing almost every cloud vendor offers a version uh interesting versions of TEES for

workloads um um there's there's a few of them um we're probably going to focus on just TDX So a attestation this is an example I'll go through. Um so three main stages you can think of. So measurement the actual attestation and the verification. So measurement is when your TE starts up you have a lot of um data points that the CPU measures like what's the software what's the firmware what are you running inside what's your docker what's your environment variables and couple and a lot of other things that you can also specify to a test or to measure so measure is just recording

like you record this in a giant JSON structure that's what you'll probably mostly see and you know they hash it shall compute hash and somebody will sign it and you know the usual stuff. Um the measurement is primarily to make sure that you know what is running inside a TE is what I measured and that's where that is one of the core important parts this the CPU measurement and other stuff it measures like the trusted computing base what firmware version am I running what is the software version of the GCP's orchestration layer itself etc etc so um once you have the structure someone worthy enough or you know the trusted

computing base in this case needs to sort of sign it. So there is a key that is you know when the hardware is generated like by Intel or AMD it is burnt into the the hardware layer and rooted in CPU and that signs off and you might be thinking oh if anything can generate a quote and can can it's signed off I can spoof it. Uh it's not. is is a rabbit hole if you want to dive into um there's very specific processes which can request a quote and even the signing process is not give me the key I'll sign it is hey can you sign this for me and this is my attestation to the fact that I was approved by this trusted process

to sign this quote and I haven't changed it and that's a very high level thinking of how quotes from the hardware measurement is signed and provided to you um in like this JSON structure here. So verification the third part is what you know we all kind of fight about. um the verification you can think I've come across like two mainly two different ways where interprocess tees like TE talking to another TE within the same CPU so to speak you can get away by not attesting a certain few things um to optimize for like TPS or

RPS or some of your apps but you have you still have the same level of verification because it is the same CPU and there's some optimizations that people are working on but the most common one is the generic verification so if you were given or if I was given this JSON structure like I this is signed over etc etc here's the verification code let's start verifying this so you can see is the mouse shown yeah um no that's not useful can I zoom in no okay um is this visible at all no little bit okay um ISS issued at by Google APIs here the supported

attributes is quite interesting it says latest usable and stable these values mean very specific things in the world of GCP so latest means latest firmware that's all I want to do and if you know the verification like a quote comes back and says this is stable but not the latest you as an app developer or you know in your operator set so to speak can reject this uh operator from joining your entity saying that like you're not running the latest and I don't want this. So that's one thing usable is probably the least where it can tolerate one or two attacks and you know version bump and stuff like that. So here on the right side top you'll see containers container arguments how did this docker

start? What are the arguments? Um down below you'll see the environments like what is this docker started with what environment the image digest the docker hash uh image d that's publicly referenceable and the image structures the layers that you can get and GCE spec like uh Google cloud specific stuff and here you can see this is the confidential space and this is the software version that you're running so this is a you know this is on the lighter side of a quote like a quote can be really really large depending on what all things you want to you know verify or add as an app developer. So if you were verifying say all the docker

container versions but you weren't verifying say the latest um attributes. So if you had only stable or say usable and there was an there was an attack intel patched it GCP patched it but you were one of your operators that were still running an older version or something. Now that's an entry point for them to start you know playing around with and you wouldn't be um you wouldn't know about this until like you updated to say that you should only use the stable version. So it is a way for Google compute or you know Amazon whatever it is to sort of specify that these are the versions this is signed by the hardware that is running it and you

can verify this all the way from the hardware manufacturer AMD or Intel because the key that is rooted in the hardware actually is signed off by the Intel PCS or whatever the certificate authority that they control. Um yeah so that's the JSON [snorts] structure is what mostly people will use to sort of understand what's happening. Um the attacks this is the most recent one that um took Twitter by storm and a lot of people screaming and it was fun to think about this. So um I'm not going to go into DRAM interposer and you know RAM speeds and stuff but the one of the two

of the main things that people were fighting about were physical access. So one of the things that is a debated topic and Intel has taken a very interesting position on this is physical attack is according to Intel not in their um threat model which is interesting but you need act physical access. So if you need to walk in into a data center with all the you know the measurements and things to sort of get at the chassis that controls you know your CPU to try to put all these things there to measure. So physical access is one of the [snorts] um attack vectors threat

models to actually see like there are side channels of course but the main one is the physical access and the other part is the components required to perform this attack was just a couple hundred and this wasn't custom sourced or anything this was off the top like I think they bought it on eBay or something. So they were able to perform or extract like close to keys and other things and almost started spoofing or probably spoofed for 500 couple plus dollars and a physical access to this. So this is something that app developers kind of need to take into consideration that if

you want to let anyone run your your app and you want to let them in your operator set so to speak um you need to consider someone doing this and there's a full description of how to do this. So they will try to do it. Um couple other attacks uh wireup.fail was probably from the same folks. Um this one was attacking the latest and greatest Intel TDX, AMD SEV um and couple others. This was um attacking SGX primarily. So the again similar attack vectors which is physical access and couple hundred dollars that you would need to uh construct and perform this um um these attacks. So the one of so of the two

things physical access is something that everyone's trying to solve in very different ways all the way from sending TE's to space to you know very interesting stuff um but this is something that caught um some interest from our side which was proof of cloud in the sense that CVM here is confidential VM um would attest to a quote that something like you saw in the JSON structure and the TPM also um would quote to show that it came from the same machine and the TPM um certificate was issued by one of the vendors that probably you want to allow or whitelist

or do something so you can verify like oh came from Dell Super Micro and Google whatever production environments. So you can and they also go to like you know data center location and things like that but it's it's a very interesting way to say that you anyone can join but you will have to run it in a specific cloud sort of a statement. So it's you know it's it's getting there and the alternative to this is trustless tees and there's a whole um research section on that as well. Um but this is one of the interesting ways that people have been heading towards to sort of say that you

know it's a it's a compromise. It's not the best, but we can still do a lot of things and verify and you know within reason the data center is protected by people with guns and a whole thing and it's data each data center has levels of certification and I think most any of the bigger clouds have level three certification. No one's gone to level four where it's like autonomous entities like going and plugging in and doing stuff. Maybe data centers on Mars will have that but we'll see. Um so I just have a couple minutes. So um one of the main takeaways when we started this journey was we started with SGX but

we ended up with VMs full TDX CVM mode and that's where a lot of the research is going and a lot of investment from major cloud providers are also going and the other hard part is you know cloud providers aren't really that open to giving out information on which data center how is it protected can you tell us your operational procedure. They're not going to answer any of those questions, but you know, it takes a few companies asking like, "Hey, we want to bring a few hundred million dollars with you. Can you answer these questions?"

Maybe they will. So, we'll see. The other part was hardware route isn't perfect. Ex. Those attacks alone show that, you know, it's easy enough to extract and you don't have to do a lot of complex things, especially when it's like listed out. And there are dedicated companies whose whole job is to break tees. So it will happen. It's just the fact that it's cool. You did it, but can you do it on my machine is the question that everyone wants to answer. And you know they're protected in the data center environment and attestation for all the security folks who would look at or audit like a TE implementation to say that like yeah this is cool. The

attestation verification and the parts that are verified to the statement that the app developer or the security engineer wants to do is very important to take into consideration that it's not just enough you just generate this quote and say like it's cool. You need to make sure that you're verifying the right parts and actions are being taken onchain, offchain, whatever the app wants to do to have your tbased app function properly. Those are some of the references. Um you're you know uh feel free and um there's been a good amount the last one uh there's been a good amount of uh effort put into different layers of how an app developer would

need to take a tbased app security consideration and the guarantees that it would make. Um yeah that's pretty much all I had. Um I can you know uh talk to anyone else about each of those as a rabbit hole. I don't want to dive too deep into. We'll be here all day. But um happy to talk to anyone else. But um yeah, thanks [applause] All right. Uh for the next talk we have

Sang Yang talking about insecurity through obscurity veiled vulnerabilities in closed source contracts. Welcome Okay. Oh yeah. Uh hello everyone. I'm

Sean a Phan at Yo University advised by Professor Fanjang. So my research interest include the defy security consensus security and many design for decentralized ecosystem and today I'm very happy to share about recent study in defy security. So this is joint work with Taiwa a and fan. Yeah. So I believe everyone here is very familiar with the uh blockchain. So for blockchain we have layer one like Ethereum, Binance, Solana. We also have layer two like Uptron and Base and we have many protos on top of it like

landing protos decentralized change and ors. Yeah. So with this uh protos we have a eosystem where users they can perform uh activities on top it. So this called the defy e system and users can have their device activity on these blockchains and uh this create a new task of perfect seating behavior called MVV where the transaction ordering matters. Yeah. And uh new player come in. So they see the prefable transaction opportunity from the man pool or from

the branch state and try to capture the opportunity through their own chain smartphone chat. So those player are known as MV searchers. Yeah. So their tone chat are known as MV bots. Yeah. Okay, so we know that the top MV boss they are very profitable. They earn a lot from the onchain activities. So we can see the total app charge revenue in a week is more than 2 millions and of this uh inbox they are total source. We

uh literally know nothing about their business logic. Even though we can maybe do some reverse engineering but still a lot hide them behind the tone chart logic and maybe we have one question that yeah even this contract they are so portable they host lots of assets on their contract were they attacked by adversaries before. So if we search some attack against MV boss on Twitter, yes definitely we have from 2021 to 2024. So we can find at least three attack against MV boss and there's nothing new on the sun. So every boss they were

probably bouncies and their asset was transferred to another address. But uh are those uh tasks for a complete set? Uh or no. So otherwise my talk is over and I have nothing to say. So today I will talk about new attack vectors which we called MV fishure attack against MV boss and then I will analyze what's the security issues and what's the challenge behind the security issues and the last I will propose our solutions standf yeah so first let me explain the idea of MV

we finish a task. So I think the key idea is or the key issues is not very hard to understand. So this is essential mechanism. So we know that temptation on blockchain is very expensive. So which means if you want to do a reader permission chat is also very expensive on blockchain. Uh look at this example. So this is a reader chart against whether uh transaction to is from a unis swap w3 pool it will cost about 450 deaths. But if we do something else we already chat whether the transaction orange is from a site address is only

cons about eight deaths. So as a perfect driving contract all of the players they may consider maybe I can sell my desk and maybe use the shan.org one. So should I use that or will it cause some potential issues? Yes. So [snorts] when we try to use orange asententral pattern everyone will try to bypass this asententral patterns.

So the idea is of MV fish attack is that how can we be part of the MV supply chain. Yeah. So when a searcher try to extract NV from their tone chat so the NV sub will include many other tone charts like Yas20 to chart tone chart or the swap pool tone chart. So this pawn chart is involved in the same transessions which means if this tone chart are malicious they already bypass the the asset control mechanism. So the next I question is that how can we be part of the AV supply chain. Yeah. So

here I want to first share some data with you. We uh analyze the transaction on Ethereum from July 21 to April 2025. So we identified at least 104 attacks against MV boss. Yeah. So the total loss is 2.76 millions in total and the one single largest stat that cost around 600,000 dollar in total and our further analyst showed that this attack even include three variants. Yeah. So then I will uh show different uh MV fish strategies and

first uh so we will analyze the attack strategy but most important don't practice attack strategy in practice and not guarantee you will win or loss or any little issues. Yeah. So the first I think is totem base and efficient attack. This is the I believe a most traditional one since 2021. So the idea is very easy. The left side is a tatter's workflow. So as a tatter I first deploy a malicious totem which have a bad door within the token and then I create a pool for the malicious totem. So it can be any uh standard pool

like unis swap v2 or v3. And then the most important step I create NV opportunity. So for example uh swap that sly change the pool price. So the MV searcher they will identify this MV opportunity and they believe so here is opportunity for up charge. So I can do that the searchers they start try to extract MV they will involve them bot the M bot will try to interact with the ES20 token.

So when the ES20 token is involved then the bad is triggered. So at that same time the transaction oh sorry the uh asset central mechanism is already bypassed. So the uh yeah Malaysia token they can explore the vulnerability within the MV tone chart. For example the arch within the MV bot chart as this tone chart may need to uh allow to any swap to finish their defectivity. Yeah. Then the next one. So the searcher now they are smart. they will check whether the Yas 20 token is standard or not.

So in this attack now the attacker they doesn't deploy a malicious token instead they use a malicious pool. So in this case they can use any other uh standard Yas 20 tokens but they trade their own pools and similarly trade opportunities for the searchers and searchers they are very happy they only chat whether toten is good or not and they start up charge then the battle within the pool is triggered. Yeah. Similarly, the MV bot will be spotted if there is a vulnerability. Yeah.

And the last one I think is most interesting and uh in this case the attackers they used standard Yas 20 totens and even standard pools but they found another possible malicious address that based on the new MV refund systems. So the MV refund system that brought from me will request that the searcher if they extract MV from their system they need to refund a sufficient address within the same transaction.

So the searchers they may chat whether the pool or the toten are little or standard but they may forget that the refund address could be a malicious tone chat address. So they just do the up charge and the in the last step they refound the address uh some ease to the refund address then the bad doll within the refund address is triggered and finally it's part and we bought on chat. Yeah.

So now we know the fact that any boss they keep suffering losses. The question is that why do they not use tool to secure their tone charts or in other words so if they use what are the challenge to prevent this tool from being useful? Yeah. So we have summarize summarized several challenges here. So first the challenge is tial flow ofation. So we know that the uh 700 developers or this MV searchers they may try to involve tial flow ops to protect this their business logit so it's very be

harder to be reverse engineered and or they may just try to optimize their desk usage and the byproduct of that optimization will also be the control flow optimization. Yeah the most important thing is that when the tflow opation is introduced, the most of standard tools they can not work. For example, if you use some stats tools, they will send the most to the wood within ton chart is not reachable. So they will tw those who were told and they say this tone chart is on not one bowl and yeah then the hiden

vulnerabilities will be triggered by other advanc attackers. Second, even if the tone chart doesn't involve any uh control flowification, the tone chart itself may still be very complex. Uh this and we bought ton chart, they may integrate many features like fresh loans, trading on different uh deaths and some other features. So an analyze tools they may turn out when we try to explore the many different state and third so when we try to write smartphone chat we may hardose some data in our tone chat and

the set analyst tool or other tools they may not very accurate when they enter the case that if a parameter is partially trollable. Yeah. So they may just see this uh parameter they are safe as they are harded and the adversary cannot control. Yeah. Uh therefore to solve these challenges we propose our solutions based on our observations.

Yeah. The first idea is how to deoffestate the tent flow ofation. So this is based on our observation. This is very interesting design. EVN specified that every little jump stationation within the bode should be marked with the battle jump nest and with this feature so we can mely let all the little jump destinations and try to rewrite instruction to made the t flow is so we do. So the left side is original to we can see the jump here it relies on a runtime value from to data. So which

means they cannot be decide during the set an endless. But if we rewrite the tone chat and we insert some table here and we can rewrite the indirect jump to a direct jump and every every jump destination now is a stat value on the stat which can make stat NS or other NS feasible. Yeah. The second idea. So we know that the complexity smartphone chart they may include uh many execution paths. So if we do the blind pass exploration it will be very slow for such compressed smartphone chat. This is a well-known

issue about the state issue. Yeah. However, sorry, we also observe that for smart home chat, we know their real world execution trace. Yeah, the transaction is public available on the smart on the blockchain. So why we just prioritized exploration based on this real world trace? Yeah. So within the historical transaction available from the Sah uh blockchain, we can analyze which assertion pass is most frequent and we can try to prioritize our exploration to this path and see if there's a hiden vulnerability within the

assertion path. So we can guide our symbolic attution based on the historical transaction and try to find if there's a vulnerability within the most frequent attribution pass. Yeah. So the final idea is to identify all controllable or risky parameters. So here we plus uh 10 analysis with uh 10 analysis to identify the all parameters that are controllable and we also have uh collection of the risky parameters.

So if a parameter is not controllable but still risky such as the function slatter of transfer which means the adversary they can control the parameters and made any transfer to another jazz is still very dangerous for the uh tone chat itself. Yeah. So putting this idea together we have standf the input is smartphone chat and if the smartphone chat is a faceted we are first dealitated and then we'll do a histoal transaction driven small execution plus 10 analysis and we will identify the potential vulnerabilities and first finally we'll try to

automatically generous exploit against it. Yeah. So here I will tweet those through the uh our evion results. Yeah. So first is about the deacation result. So we apply the stand to the state arts stats to data horse and see the total before and after the stationation. And we can see after deopation the total coverage is very close to 100 which means that the staff can effectively retire the tension flow logic and enhancing the efficacy of the existing stat analyst tool.

Yeah. and sedent for vulnerability detection. We compare ST app with the other state of art symboling tool and we used 6.5,000 MBOS with L from different websites and as a data set we found that our tool identify the most vulnerabilities and success generate around 400 of them. Yeah, we even quantify the potential loss. So if this smart home chart were exported what would the maximum potential loss will be and the maximum potential loss will be higher than $10 million.

Yeah. So finally we chat the runtime of each tools and we can find within the time samp budget f can find more vulnerability to others thanks to the real world transaction driving support execution. Yeah to summarize in today's talk I talked about three new attack vectors against MV boss we summarize at MV fusion attack and we analyze the challenges of analyzing such tone chart include the offensation complexity and why simple pattern match doesn't help and we also propose our solutions about deoffensation historaction uh uh similar attitution plus tent

analysis And this evaluation shows its efficacy in deautheation and vulnerability detection. Yeah. So we also have a paper onab and a small blog post to explain it. And this is my website and feel free to ask me if you have any questions. Okay. [applause] Yeah, thank you.

>> Zoo, nice to meet you. Nice to meet you. >> All right. Uh, next one we have >> Sorry, Zoo. >> Zoo. Ian uh talking to us about governance as an attack vector. Welcome. [applause] >> Okay. So, hello everyone. Uh well, I'm Zoo. I'm head of research at BlockFool. We'll look at governance security to some vulnerabilities in the five protocols because of their governances and glad to have the chance to share

that with you. Uh I'm head of research in blockful where we look at coordination as our main goal. So broad scope of things that's what been taking us into governance and into Dows and we're basically a big group of gov nerds where we see over the last few years we're exploring AI for governance we were exploring reputation systems for nonputocratic governance and well being service providers on a few different dows we started finding some of the vulnerabilities that we're going to bring the idea what we look at is governance security So beyond code audits, not only uh uh faulty code can destroy your system, but also anyone

playing inside the rules that gets to manipulate the rules for their own profit. Uh one of the nice things that we've been feeling during this time as we're building this is to make those governance systems resilient and trustless. And to see the truthless manifesto published recently was a very good nudge that we're working in the right direction and that it makes sense to work towards this uh defense beyond just centralization. So governance exposes some risks but it's what allows us to make our systems resilient. So we need to also make governance resilient so those systems can benefit from uh from that part. If you haven't read this

article, super recommend you do like it's worth one. And the main goal here is to create effective ways to measure the trustlessness of a system uh in a way that we can standardize. That's how we've been working towards analyzing those risks. And well, let's jump into it. Uh the goal is to always find an attack before it appears, right? When you're when you're trying to make defense, especially uh when we're talking on a code level, if it's too late, it's too late. no way to go back. And the first moment we found that let us uh start looking into it was ENS DAO.

Last year we realized that the delegated supply on ENS DAO was just too small to make sense with their size of the treasury. The voting power was too cheap. The treasury was too big. And we were like, okay, why is no one arbitrageing this? Uh turns out that just because they hadn't realized uh ENS was sitting at $120 million without counting their own tokens on the treasury. So that's is just if and stables and the total possible voting power at the moment was worth $65 million. The voting power that was actually being used was of about 24. So let's say $25 million take 120 million home. That's a good that's a good arbitrage. I I would take it if I didn't

care for protecting the Dell also. Uh but not only economically viable attacks are the risk, but also ways that make them cheaper and make those attacks even more profitable. Uh ENS as one of the examples of the things in ENS DO that would make this easier uh is their governance implementation for voting delay. So whenever a proposal goes uh to vote before between proposing and start voting there is a voting delay. That's where you have time to actually discuss the proposal to actually get more aligned delegates to to join this delegation pool and vote. And on ENS it became quite clear that having a weak governance stack and bad economic

conditions is going to make for an easy attack. So we need to look at the weak governance stack because bad economic conditions just go up and down. We're all in crypto for a while. We know that a bare market just comes tomorrow or next month and suddenly uh all your token prices are down and your stables on the treasury remain the same. Suddenly the arbitrage is worth it. Uh basically at this point we keep monitoring ENS DAO there's still a very good arbitrage to make. But now with a stack that has a security council in place a vetoing body composed of different entities that can look at a proposal and say this is a drain. We're not playing this game. This proposal doesn't go through. So it would just be a waste of cash to try to arbitrage that. Uh there's also full case of how

we solved this if anyone is interested to look at this one. Uh but this is old news, right? Like Dows have problems. People don't vote, treasuries get robbed. Yeah, but this is how we say things when we're in a normal bias perspective. All right. Like, oh, it's not going to happen in my D. It's not not on the sex that I use. We're just too big to fail. over safe and well we all know how how this goes on that story uh but on Dow so far this has led to some some problems and currently it's on defi dows also starting to show up uh as we're analyzing I bet it's been there for a while but no one has been really looking too much into governance

security so over Ethereum's time life we have about half a billion dollars uh stolen directly inside the rules of a DAO either by getting the Dows to buy back your tokens or just transfer the treasury to me. Different strategies, same result. Dow loses money. Open source stops getting funded. Defy pools and incentives get drained and someone gets really rich hidden somewhere in the world. Uh but in the last 12 months as we started looking into this, we've already solved the ENS case with the $150 million total loss that we could uh could have had there and have over the last year since then identified something that is even more worrisome for us. That is attacks on protocols uh

vulnerabilities on protocols that actually control true governance uh user funds, right? Like have access to change oracles to move not nice not nice things to to see while you're researching and that found we found up to4 billion dollars so far at the highest point of the of the curve for beautiful bull market. It was at a 4 billion uh dollar exposure total which is not money we want to lose from our users. Looking at all these attacks we identified patterns we're trying to work those in standards. So this is also an invitation for all security nerds to reach out join uh we're talking with EF on how to push this further and one of

their requirements is for us to work with a broader uh amount of teams. We cannot be creating standards by ourselves because we might be blindsided in some point. So everyone who wants to look into how do we standardize governance security through a more we're governance nerds. need more security nerd perspective in some of our flaws here, uh it's very welcome to join. But what we what we came up to uh with this was a framework for analysis and defense based on four different verticals. We're looking at economic conditions, token distribution governance implementation, and activity. Economic conditions is basically is it profitable, right? Does it cost more than it has on the treasury? Then I'm

not going to do it. Uh that goes to also token distribution. that is understanding if the power can even be acquired like oh it costs 10 million to rob 150 but the liquidity is 1 million so that's then you have to slowly compound your attack until you're ready and that's what we want to identify before it happens uh the governance implementation so things that could make it much easier so can your governor contract be spammed can I make 10,000 proposals on mainet and now I have to vote for one for it to pass and delegates have to vote no on 10,000 and let's see how that goes for you to defend uh and governance activity. So, not only are those tokens available to defend, but are they actually paying

attention? Are the investors in the US allowed to cast their votes or are they going to have regulatory trouble and let the Dow go down just not to get this trouble? So, all of those things matter when we're measuring how we defend those treasuries. Uh oops, this is repeated. Uh and the challenge here is not only to solve this because solving this is easy. put it on a foundation, let them call the shots. Now they can just veto everything. But you lose a lot of the things that make it worth it doing, right? You lose trustness, you lose resiliency. Now you're bound to the laws of the country where the foundation sits. You're bound to [snorts] incompetence uh in a centralized uh entity or corruption, whatever. Uh you all know why we do things in a

decentralized manner. And we believe that getting holders to take part is the is the way here. When we say holders, we're not talking like millions of people in retail. We're talking understanding alignment with stakeholders and investors that if you are holding millions of dollars on a Dow token, that governance is what keeps your assets safe. So, okay, you want to put at liquidity provider 60% of what you have, but let leave 40% at at a delegate you you see alignment with. find a security team and hire them to represent you or get get that uh that voting power you have being useful for the security of the Dow, not just to make a small LP fee that's not really going to move your needle. Uh

the thing is a few in the Dow today can already make decisions alone. Both ENS and unis swap need not many delegates of the top ranking to pass things. And right now we're just lucky that those are not abusing their powers. Some of those are centralized exchanges. Some of those are early investors or uh early contributors. But well, it's still just lucky that they don't change alignments that they don't move for their own benefit inside of the collective. Beyond that, a lot of power sits on centralized exchanges and that's how most of the attacks we've mapped came to be. It's basically much harder to identify uh 10,000 wallets getting $5,000 from like a diff

from a few sexes and then getting suddenly everyone delegates and votes and proposes at the same time. And when you see the attack is set, the voting power has been counted. There is not enough voting power to counteract and you're going to sit and watch for the seven days of the process how we cry about the destruction of the Dow that's been built for years. And even worse than that in my opinion is to see delegates that have that delegation that have an investor that have a big holder that are behind them saying like hey you can represent me that you can keep the Dow safe and both on compound and unis swap most of those top delegates don't vote. Uh this is starting to change on unis swap curiously with duna now being

legally compliant apparently encourages investors to participate. Who would have said? Uh but on on comp is specifically we see Humpy that's like the the comp attack attacker has been trying for over a year doing his moves trying to take power. He's more active than most of the other delegates and that's just absurd in my perspective. Those conditions together we've been calling it the quorum crisis. The quorum crisis is a absurd lack of participation in Dows that makes although the market cap is bigger than the treasury the active market cap is just can be ignored and they leave us exposed and if we're exposed we have to assume Lazarus knows

those types of attacks they've only like they've taken $500 million wow okay I find a lot of money but compared to scale of attacks over all time that's not that much but if this becomes a pattern uh on on our research been pointing so many of those different dials exposed uh it could be like a serial thing if we find a if more uh qualified actors get to play so we have to see the risk before the problem just like we saw it on ENS we're now seeing it on compound compound faces a very similar situation of what we were talking before but in an even worse position uh while the treasury is big and delegated supply and active supply are mall. Not only that is

going on but uh compound different from ENS uh has a governance that has access to the protocol itself. The comets are owned and commended by the governor. So that means that the capture here is not only draining 150 million. This could touch way more money. Not only the treasury Dow money but my money, your money. That that that is another level of an issue and it's been fought against. [snorts] There are people in compound now trying to call that attention, trying to make that move to change that. But at the same time, we still see that Humpy, the leader of the adversarial coalition, the red teamer here, he has more voting power right now than the average turnout. So, uh,

recently he was able to block by himself. Oh, we say by himself. I don't know what are those wallets, but let's say it's this coalition of Humpy. has been able to block a proposal to fund the Guardian Council, the guys that have veto power. Uh so if he attacks now, the guys that have to veto him, they they just didn't get the funding because he said no. And this council has to be renewed next year and maybe he can say no again. This is his public power. We don't know how much he he holds in any centralized exchange. We don't know what addresses that are laying dormant are also theirs. We are still to find that.

And if any of you is humpy, please let's chat. Uh we we saw that uh last year in in one of the attacks that happened there. Uh we mapped that saw what was going on. In the end, he passed the proposal and accepted a new product from the DAO to cancel it himself. He could have taken over and he didn't. So this is a complex actor to understand but the opening is still there and we don't deal with trust. We deal with making guarantees that our systems work and are not capturable out of thin air. So if we have to assume that Lazarus knows Lazarus being generalistic attacker symbol here but is an as an attacker that is wellunded that is creative that

is smart and that knows that we are all normacy biased. No nothing's going to happen. We're all safe. We literally get in touch with D and say like hey guys you are at risk and they look at us and say now nah we're fine believe us like we we got some defenses you haven't seen and I hope they do but I find that it's more more of an ego and overconfidence thing than anything else. The thing is it's not only getting that 51% supply there's many other ways to make it cheaper. So even if you're one to one, well let me drain it, lose money out of the drain compared to my cost, but then I'll short the drop and I'll have borrowed some like you can start compiling mechanisms and even like in an

unfavorable uh condition still profit on top of an attack like this. And if we assume that Lazarus knows it means that we have to know too. And knowing ahead of time is what we've been trying to make possible. Uh we've been trying to butt up solutions with some of the Dows that we are working with. Uh this work has been mostly funded by Uniswap Foundation and ENS DAO. Uh to try to start making ways for people to know those things I'm going to show are all public and free to use. Uh if you're interested into keeping an eye on that, feel free to go for it. The first one is a system to evaluate economic and systemic risks. So we have security stages, risk areas, and we're mapping that on a dashboard that we're indexing the data ourselves. So we don't have to trust anyone on the way. Oopsie. This is

buggy. Uh notification system so you can keep track of different uh changes in in voting power. Keeping track of your delegate if they're not voting because we see that delegates that are unactive are one of the main issues, but also the people that keep their delegation with people who are inactive. So just making sure people know when they can change it and designing new incentive systems so we can bring people bringh holders to care on governance again to delegate again. Uh it's we know it's kind of unfair to ask people to say like hey leave your money here not making any profit so we can keep this thing safe.

So there are ways that should be explored how around how we can incentivize uh this type of action. Basically it's dangerous out there uh in governance. The idea is to make this anti-apture framework so we can all apply it on different spaces. Again, this is an invitation to join and collaborate. We're really looking forward to expand this now beyond the models we look. We want to be able to look at Lido, a sky that are the three main ones that we are not being able to cover because of the changes of models. We want to make something that is standardized and can be replicated. So, it's taking our time to get to there, but we're already mapping compound uh and unis swap mostly and TVL. Those are the ones that matter the most that we're

looking uh basically yeah we're looking at a few dials in a few different ways to with the goal of making it legible and making things that you need to look in a contract easier to see and track and finding the risks before they're critical. seeing like how for example if there's a big change on how the money from centraliz the supply on centralized exchanges drops a lot and delegated supply goes up fast that is a good signal you should pay attention to what the happening that's it governance was never easy uh and quoting from the trustless manifesto we choose to build trustless systems even when it's harder uh we hope other people do too and that's it thank you

for your attention AMAZING [applause] STUFF. [applause and cheering] All right. Thank you, Zuk. And for the last talk of the evening, we have Ray Orle talking to us about when one dependency breaks everything. Securing the web three to chain. Welcome something else. Just

Okay just switch it to present. I have an HDM. >> I don't know if the table then >> put it on the floor.

>> Yeah. Or sideways. Okay. Display. >> Yeah. It didn't work. I also shared the link if you want on your computer. It's fine. I think it should have been right there.

Right. >> You have another computer. >> We do have your presentation already. >> Yeah, that'll be fine. Yes, you also have this one. >> It's already work. I don't know if your pointer will work all that distance. >> This goes forward. This goes back. >> It's very weak for some reason.

Okay. Uh, I'll do my own time. Perfect. We can begin. Hi everybody. Uh, so as I mentioned, my name is Ray. I'm one of the team leads and a security researcher in Stora. Uh, today we're going to talk about when one dependency breaks everything. Basically, I'll show some examples, real world examples, things that we found in the wild, things that we saw other researchers find where your system, no matter how well audited, how well secured, you invested a lot of resources to make sure that it's perfect. But because you're relying on some assumptions and relying on some other code that you haven't developed

and audited yourself, you introduce weak points to your system. Uh, it seems like you have the either [snorts] the wrong link or you're showing the hidden slides. This is the previous version. I mean, it's fine, but if you can >> It's a It's a shared link, so it should have updated. We could do this, but it just has bad graphics. Could you see one minute if you can fix it while I So, we're going to talk while they see if they can uh figure it out. uh we're going to show uh a few different examples uh which show how supply chain attacks come in various forms. Uh one of the forms is going to

be where you're using uh uh where you're using a package you include some functionality that has been well audited but the way that you're using it isn't trivial and it's a bit more robust to what you need which introduces bugs. I think guys, if you can't figure it out, we'll just continue with this. Okay, so some of the graphics might be a bit messed up. I'm sorry in advance, but it'll be fine. Uh, so this is me. So supply chain in the context of web 3 is when you rely on other packages uh to develop your code when you rely on extensions for your VS code things like

that anything that helps you to develop your final protocol is what we call supply chain uh so the first example that we're going to talk about is a pretty old bug that was uncovered which which is in a package called timela controller uh [snorts] the core purpose of that package is pretty simple you want to have a functionality which allows you to uh delay do some sort of time lock on some operations in your code. So you want to schedule some sort of uh call or function or configuration change and you want to give some some users of the system the ability to react.

So the bug that was there uh was that the way it's supposed to work is you're supposed to schedule your the transactions that you want to do give some sort of allocate some sort of delay schedule delay for other actors to respond to challenge things like that and then once that time has passed you can you can execute an executor can execute the vulnerability itself was that in the batch execute The actual check that the call is scheduled was after the call itself, right? So you might be saying, okay, sure, but what does that change anything? [snorts] This contract was self-governing. So the the the initial

role of this contract was admin role. So what an attacker did was he did a batch of multiple different transaction. The first thing he did was he set the the schedule delay to zero. Right? So now he can schedule for the same block as the execution. The second thing he did was basically make the attacker the admin of this core protocol allowing them admin privileges to your code to your protocol. And the third thing he did is he re-entered he scheduled after executing the first two he actually added it to the scheduled transaction.

So when the check at the bottom actually check whether or not this was a valid thing to execute, it was after it's already been inserted and because he can change the delay to zero. Uh it it's valid, right? It's the same block that was scheduled. That's fine. This is frightening, right? This is a few years ago. Um I think uh the researcher, the white hat who showed it was paid like $25,000. Uh I think probably should have gotten more, but uh yeah. So, let's go to the >> updated.

>> Yeah. Yeah. I was wondering what happened. >> Perfect. Yeah. This is the nicer graphics. Thank you. Uh, okay. So, this is this is a case where you truly just have to be paranoid, right? This is code that is well documented, right? It has been audited. You can argue that it's not your fault, right? It's uh if you can't trust anybody who what you can do I argue is always be paranoid right always assume that if that the bug can be hidden anywhere possible if you're getting audited don't throw the scent of your auditors one of the worst thing you can do is you can tell them oh oh yeah don't don't look at this right it's

completely out of scope obviously you want to direct them into the areas that are interesting but if you're telling a researcher that something is out of scope he is blanking on Whereas if you don't say anything, he might investigate. And a bug is a bug. It doesn't matter where it is, right? Okay, let's go a different route, right? Another package uh which was used very reasonably. This time the package doesn't have the bug in it, but the way it was used. So this is a rose package. Uh I think this is also from a a major like developer, but again this is not like a thing against them specifically.

This is just examples that we sign in the wild, right? So the way it's supposed to be used is you grant some sort of privilege roles to some actors, some addresses, some smart contracts, things like uh allocators, uh admins, some sort of executor, pauser, some sort of roles which gives you extra benefits. And then whenever you have a privileged action, you can check if that role or subset of role is actually active and usually do it through a modifier, but obviously you can do it through other things. Seems really reasonable, right? I'm sure your protocols are protocols that you've audited. You saw a pattern like this or even this exactly. So, uh again, right, it's harmless. It's well audited. Uh it's out of scope. But we had a scenario where we saw that

uh a developer already had this functionality and they thought, okay, we have it. Let's expand on it. Let's use it for uh the banned role, right? An actor who's done something that is against the protocol. So they're supposed to be banned and they lose the funds because they can't access them anymore. So this might seem reasonable, right? You might say, "Uh, okay. Yeah, sure. What what are you going to say? What how is this bad?" Now, if we go up a little bit, right? There's there's a a small note that I put here, which is it's a bit documented, but not super well. This is supposed to be privilege role. So the idea when this library was developed is you only do it for privilege roles. And as you can imagine an admin or in this case maybe not uh

well some versions don't allow for admins themselves but you can always re revoke your privilege. So the banned user just revoke being banned which is obviously not ideal. Now this if you're getting audited this is like three five inheritance down the line right your auditors are going to have to work hard to find this. So right the the best way to to get around that is to basically if you're incorporating code that you haven't wrote invest the time to research what what it's doing right uh and document it somewhere for yourself not for any not to help any other researcher not to help any other auditors just for you to know

what you're doing so you don't have those mistakes if your developers changed things like that right the the next one is relatively new. I had something older uh and then a month ago uh Glassworm uh was uncovered. So I'm [snorts] not sure how how well you guys know that. So Glass Glassworm is a VS Code uh extension worm. So what it does is it's a malicious extension for your VS Code. So you can imagine something like maybe it does like a pretty font for some things, right?

Maybe it gives you some AI capability, right? You can imagine how you might have on your computer right now some extensions which you're not sure why you download them. Maybe you got like uh Ethereum and you saw like six different ones and you just said I I'll get all of them, right? I'm not sure exactly which language package gives me the best functionality. Right? So one of them had the malicious code in it and they did a few unique things there. Uh one of them is the malicious part of the extension was developed in unprintable uh co well uh unic code right so your VS code browser your notepad your terminal whatever you try to if you go the extra mile to see what what it's doing it will show you just characters that are look

like spaces it will be nothing you won't be able to work with it if you have some sort of um client that's supposed to trigger if there's something malicious it won't know how to handle Uh so this is this was in innovative but not not that much like we've seen that before maybe not in web 3 extension context but it's pretty well known that if you're doing uh payloads like that you can hide them. It takes a little bit more work but usually that's not the hard part. The the the big thing the thing that they actually did which was unique and it's the first thing we saw the the command and control center was onchain. So this is a bit of lingo of like uh well hacking in general but command and control is how you tell a computer that you already have malicious

code running on it. How you tell them to download a a different payload, usually a bigger payload with more capabilities or uh this one I think stole like 50 different uh wallets. They have integration for their keys. Uh, and another thing that they had, not not on the original small payload in the extension, but on the bigger one that you download later, is it actually checks if you're developing on a GitHub account extensions yourself, and it inserts the original payload into the extensions that you're, uh, developing. So, uh, this was uncovered like a month ago. I I I think I got the first researcher who reported on it. I'll show you a link in a moment. But all this how to download the bigger payload, how to control your computer was actually is

done onchain. And you can look at those transactions where they say, "Okay, now download this payload. Now do this." Scary stuff. Uh you can you can scan this uh as far as I can tell, he was the first guy at least that I saw that reported on it. Uh maybe somebody else did it first. Uh he is a better article than what I'm summarizing here. Uh I'll give a moment to anybody who wants to take a photo. You can also search glassworm on Google. Uh very interesting. Okay. So we saw an example of just code that had bug in it. Really hard. You have to be paranoid. Uh we saw an example of uh a code that is okay but you used it incorrectly. And now we see

that even your IDE could be malicious. Right. So all is lost, right? Yeah. Uh so there is no security and and what can we do right there uh there's so much that we can do maybe we'll work uh through uh pen and paper in a in an isolated cave uh it will be more secure but let's think about actual things that we can do in order to make it uh a bit more secure I'll be honest it was extremely hard to find four words that start in the same letter and so I did three um so these are actual things that you can do and you can recommend if you're doing audits and you can implement that would definitely solve the things that we mentioned until

now but will generally make your supply chain your packages that you're using the de debugging of your code maintaining it all that stuff faster and hopefully I managed to show you that it won't take a lot of time because we don't want to do stuff that's wasting our time so we have document deflate delve and document again looks good right uh so document right uh if you're using a piece of code that you're haven't developed yourself obviously I recommend it for code that you're developing yourself but this is not the point of this talk specifically why you're using it which version are you using right what sort of constraint caused you to actually uh work with it how are you using it do you do something

that hasn't been strictly the use case of it do you expand do you add functionality uh what is your cost if you stop using it. Can you develop your own code? Can you change the design to avoid it? Right? This is not just for packages that you include in your in your protocol. This can be also for VS Code extension, maybe operating system, right? If you're using some weird random build of Linux that has a lot of like cool agentic AI stuff, right? Uh would it really cost you to move to something with less blow? Maybe. I don't know.

So next up, deflate. This is how we trim we trim the fat. Okay. Uh it's so easy to try new things and we all are exploratory. You want to make sure a process is as good as possible. I understand. But specifically when you're developing protocol that's going to hold hundreds of millions LTV, this is core things. Minimal is best. Okay. Treat it like a classified army top secret project. Okay? Do take the minimum things that you need and try to treat everything as potentially malicious. Right? If something can be removed, a VS extension that you don't

know what it's doing, remove all the extensions. Start from fresh. Download just the one that you need. Maybe don't use VS Code. Use Notepad++. That's a joke. Uh if you can't remove something, reduce its functionality. What do I mean? Uh, don't develop the wheel from scratch, but if you need a tool that does a 100 million thing, maybe it's a parser that can do, this is not strictly web 3, right? But it's a parser that parses images and videos and every format in the world and you only need it for PDFs, just remove everything that's not PDF.

Reduce the attack surface. Uh, if you can't reduce, you might want to develop yourself. Obviously, there's cost in developing. uh ask yourself do can I if I can't augment if I can't change what the thing that I want to use is doing can I develop myself something more lean more minimal uh that does the only thing I'm doing and nothing else uh if you can't develop be suspicious right uh I had a I had a a session with a with a client and we basically had a week where we investigated all the services that are running on their development uh VM machine and we went a bit overboard. I'm not saying go that far, although you

might want to, but be suspicious of anything that you don't know why it's there, how it's used. Uh, if you're auditor, uh, you or if you have, if you're research inclined, get wire shark, whatever. See if anything is calling out. Just be suspicious. Delve. Um, if you're using a piece of code that you want to add, right? Uh, or an extension, put some time aside to delve into it, right? Internal research, figure out what it's doing, right? Internal audit.

See if that's something that that's needed. If there's other things on the market that is better, right? External audits, right? Uh, if you're if it's super critical, uh, have somebody else look at it. somebody whose profession is to make sure that you're not losing money. If you can't understand something, don't use it. Don't use it. If something is so complicated that you can't figure out this is not like developing like Android and there's so many subsystems and so many things and oh no, what can we do? No, this is this is web 3 so far. It might not always be this way, but a lot of the things are simpler. A lot of the ecosystems are simpler. you can conceivably understand your own protocol and if you can't try

to see if there's any version of it which you can understand right okay right so why did I say document twice uh I don't want like the worst not the worst but I don't want you guys to get out of the this lecture go to your teams your your firms whatever and just take say remove everything delete everything uninstall all VS code uninstall remove all the includes not because it's not secure but before you do that write down what has been deployed write down what has already was already used in your system before you remove some

sort of service from your deployment machine write down what it was what version it was trust me when somebody is going to post on Twitter that version 4.3 of some random package has has been exploited, right? It will be so much easier for you to look at that document and see, oh, we used 4.3 when we deploy this protocol that it's live for the last 3 years, right? Before you go ham and you tell your your product managers or whatever, we heard Ray, he gave the best presentation in the event, we have to remove everything, write it down somewhere, right? you I recommend in some sort of markdown file on on a

GitHub something that is text. Don't don't use like a like some sort of proprietary sort of Slack [snorts] notion thing that in 3 years might be removed and nobody's going to know what the document is. uh take a while to ask yourself what I'm doing, why I'm doing it, which version am I using so that if there is some sort of worst case scenario, you have a quick lookup that you can check and see, have I been wrecked? So, uh we talked about document delve, uh deflate document conclusion, right? Supply chain in most ecosystems is one of the hardest things to audit and to maintain. Right? If you think

building a car, right, they have to take into consideration where every component was built, right? I I had I I I audited Intel code for a few years and we had to come up with solution that if you have a factory in China that produces a specific chip, uh how do you secure that the bits on that chip are encrypted so that the workers in the factory can't leak that information out? Thankfully, we're not there, right? It's not impossible. That's something that you can do. That's something that can elevate your your auditing. It's something that can elevate your code so that you won't be wrecked. so you can help secure DeFi and so that we all have just generally a better time. Not everything is lost. Web3 is a great

place to be in. Make sure that your tool chain is good. Thank you very much. [applause]