Preventing Hacks with Security Rules Written in Solidity - odysseas

Solidity Summit at Devconnect Argentina 2025 · 18 Nov 2025 · 15:40

Odysseas of Phylax Systems explains how the Phylax Credible Layer lets teams write security rules in Solidity that prevent hacks. The Solidity Summit talk at Devconnect Argentina 2025 first covers how these rules work, then how to implement them in smart contracts, and finally walks through real-world examples.

Speakers

Topics

From Solidity Summit at Devconnect Argentina 2025, hosted by Solidity.

Transcript

Awesome. So, we're just back from the launch. I I understand. So, everybody's feeling a bit heavy. So, I'll I'll try to make it super quick. Uh yeah, my name is Odicus. I'm the founder and CEO of Filac Systems. We're doing security. And in this talk, I want to talk a bit about how we are using solidity in a very um different way in our protocol, in our system. I think solidity is you know this it's a language that everybody knows and this allows us to uh use it in ways that is not just only for you know EVM development. Um so obviously Solidity was introduced you know by Ethereum as a uh language for

development. is a JavaScript like and then dab tools take it a step further and said actually you know why not use the same language to test right why do I need to learn JavaScript nobody likes JavaScript that's a fact um so yeah let's use solidity for testing right and then obviously foundry halmos you know they took it a bit further foundry um made fuzzing and environment testing uh you know more powerful implemented a version like um a form if we want of environment testing of uh uh formal verification and of course now we have fileax which we introduce solidity to enforce it

variance and runtime. So what are invariants? I want to deconstruct this a bit. So we are using solidity to allow the developer to express an invariant something that is should be true about their system always and then we enforce that at runtime right and runtime we mean whenever a transaction interacts with our protocol. Who knows what this is? This piece of code who can read it and tell me what this is? Anyone? Someone? What is it exactly? It's a fork test, right? Um, a fork test for those who don't know is basically a type of test that DAP tools introduced and

Foundry made famous and basically it allows us to run a test against uh the state um from a live blockchain basically, right? I send the the current state or historical state um instead of just having an empty state where I have to set up my own environment. So this is how you run it. You say forge test. You give an RPC. You say for which block number you want to run it and then it will populate the state from that block number and it will run your code and see you know what happens. So what if we run this command but we run it on every new block right?

So we do a force test now but we run it on every block. Effectively what we've made is a monitoring solution. We have our foundry, our fork test um suite. We have some code that checks uh my protocol against some live state. And now we do it for every state, right? We do it for every block. Effectively, we built a very uh the poorman's version of a monitoring solution. The problem is that alerts are lame. You know, you can see, oh nice, my protocol was hacked, but you only see it after it was hacked, right?

uh with a great devx though which thanks to solidity. So now we say okay let's take the same concept of that of a fork test um and then run it during the state transition function right imagine we have a system an EVM chain where we had a transaction if we have some state it enters the EVM that produce another state obviously a result and then we feed all of that into a new um EVM that runs a fork test a foundry fork test for that state transition right imagine you could write and execute a foundry fork test for every state transition that that um touches your protocol, right? That would

be amazing and that's what we've done. So in our system, how we use it, we allow developers to write what we call assertions, which are the fork tests. Um and then they can associate it with their contracts, right? They say you know for this contract and this contract I want to have these fork tests and whenever my contract makes a state transition because a transaction touched it I want to execute the fork test and make sure that the state transition was valid. So before you know without this system we have the transaction it touches some contracts we execute the contracts and then we have a result. Now for the computation to be valid,

we take the the transaction, it interacts with some contracts and then also we have to run the fork tests, the assertions for um for these contracts and only then do we say that the state transition is valid. In the very simple terms, this is effectively what we've built and how we use solidity in this very um different way. So an interesting attribute which basically we inherit from you know from for the fork test is that these assertions these computations are atomic and read only right they just read state and either

they succeed or they don't. which means that we can um parallelize them very aggressively. They also express the what and not the how, right? So you can imagine it as a lazily executed fastest, right? Where instead of having random inputs being generated by a system, the the random inputs are actually the transactions of users, right? Same thing, we have a fast test that is executed and runtime effectively with inputs generated by the by the users themselves. So the developer doesn't need to find or think about how the code can break.

Obviously it's important but even if they miss something if they have encoded the property in this like you know fast test or fork test in this property test um the transaction will not be added to the block during um the state transition. So how how does the system work very briefly? Um so there is an onchain registry or smart contracts and we allow then a team to go there and they can define them rules these assertions and then whenever a transaction uh goes to the network there is a sidecar to the validator node. So uh the network has to adopt it. Um and then the sidecar will check the trans will take

the transaction execute it and then we'll see whether the transaction interacts with any protocol that has defined these assertions these rules and we'll execute this and if the transaction violate these rules if the fork test fails then the transaction is dropped and not being added to the block. If it passes it's added to the block. So what we get here is basically um we you know uh hack prevention right basically this is almost a step level improvement in security where you will actually you know catch the hack um during the state transition if you define your properties correctly it's impossible to be hacked and another nice thing about reusing

solidity here that is a system that's very easy to use right you can just take your um you can just take your mental models you at Foundry, you know that you know your properties of your system and you can use it um versus, you know, other approaches that require a lot of context that are complicated, right? Um and part of why we we adopted this, you know, foundry style, you know, mentality and we basically do the fork test and we executed on um on the state transition even if it's not the most performant or most effective. um it is the easiest and also it is the most powerful.

So this is an example uh from the balancer. So this is um a part of the code of this uh fork test. This offchain solidity um code that runs by the sidecar. We have some new pre-ompiles. So in this particular pre-ompile we have taken all the calls made in the transaction. We have filtered them for the calls we care about. the calls that would change this K factor and then we want to we fork between the state of these calls and basically what we say is that this the K factor should not change more than uh than 3x in a single transaction in a single call basically right if that happens then we say okay obviously this is wrong it's not

expected of the protocol it's not expected for any call to modify the K factor more than that and it should fail this a very simple example. The interesting thing here is that we, you know, when we created this code here, we didn't know exactly what was the root cause of the hack. And that was important for us because a core thesis here is that we don't need to know. We just need to identify the property. And I'm sure someone will say, oh, this is that's a heristic. That's not a property, right? That's not an invariant.

Um, that's true. In this example, we found a heristic. Uh but the beautiful thing here is that either works. We have examples with protocols where we define these properties in solidity uh which are actually invariance. We define these properties that should never be broken. But also for some other cases we can use heristics right based based historical performance or historical context of the protocol. uh we can understand what are the heristics and create you know some rational thresholds where we say okay if something goes beyond that well something is up someone is trying to do something weird with my system and I don't want to know anything about that I mean I want to know about it and I I

just don't want to to allow to happen so that's it for working with me on how we use it in a very weird yet very powerful way um here's social. I'm down to chat. Thank you so much. [applause] >> Thank you so much, Odysius. Um, the session QR code for uh questions is up on the screen. I don't have any questions as of yet, but do we have any more questions from the audience for Adysius? Yes, I can bring the mic to you quickly.

Are these sidecar invariants that you run public or private? So if I'm a potential attacker, can I just simulate my attack transaction against your invariance? Uh, and if I know them already, I'm just in the balancer case, I'm going to make that K value 2.99 instead of three and just run 10 transactions instead of one. >> Yeah. So you've gotten a very interesting edge case, right? Um so we think there is no reason for this environments to be either public or private. It can be none. It can be both in a system. We f we developed in in a public way because we think that the user should know uh when the properties of the system they interact with change,

right? Uh because this invariance, you know, this code this assertions is too incomplete. Um so the protocol can do anything. Um but the thing is the interesting thing that you mentioned that is in the case of a heristic indeed here we would lose um there is information leakage here. We we tell the hiker how to go around the heristic. Um so indeed here uh probably the heristic should be a bit different maybe much lower so that the attacker you know it gives time to the team to do precautionary meas measures. But if it's an invariant then there is no signal to be leaked.

Like if I tell you um the invariant you know of a of a protocol right that's that doesn't give you any signal any information how to actually break that environment. Um you know I can tell you right now that you know your protocol should not be upgraded when you sleep. I don't know how that can happen. I don't know if your you know your private key is leaked or there's a trozen horse on your computer or you know you've hired North Korean you know people or whatever right um so yeah that's very interesting so heristic indeed but for invariance if you define it correctly then indeed telling you an invariant gives you no information but as per definition of how to break this invariance.

Another question for you. Um, for dropping a transaction that fails test, does validator need to sign up? What if a hacker waits for a validator who will not drop it? >> Yeah. So here we go into [snorts] the uh kind of worms of the architecture uh because it's a very different approach. So when we think about validators and L1s uh the approach we will most probably follow is what we call of application specific sequencing. So effectively you say I restrict the number of validators that can interact with me that can sequence my transactions to a specific set that you know follow this pro you know have

adopted this solution because I want to exchange basically livveness for security right that's the tradeoff you're doing um for L2s where we're you know focusing right now and we're seeing a lot of interest obviously you have only one party to convince um and they have a lot of incentive to be convinced because they want to attract um you know institutional capital that is very risk averse and something like that is a very familiar architecture that you can you can find it in in the New York Stock Exchange you can find it basically in any exchange in any trafi this type of circuit breakers that protect the system from um you know something bad and especially in a

blockchain system where there is no recourse once you know something happens it Um these things are more valuable. >> And one final question, invariance can be in between transaction or in between op codes. Which ones are more important and can you capture both? What if you don't know the contract implementation? >> Um right now we implement environments between transactions and calls. Uh we want to support between multiple blocks in in the past. Um so being able to fork a few blocks in the past um for op codes this sounds difficult to implement difficult to

audit and I'm not sure how much detail you get. Maybe there's value it's not something we have really explored. Um thank you for the the the feedback request. >> Thank you so much for answering the questions and for the amazing talk. Um please give it up for Otis. Thank you everyone.