Designing DeFi Resilience: Inside Aave V4’s Security Blueprint
DeFi Security Summit at Devconnect Argentina 2025 · November 2025 · 20:30
Dhairya Sethi, smart contract engineer at Aave, and Tomer Ganor, security research tech leader at Certora, show how Aave V4 is designed for security. They unpack key architectural choices, their threat models and the trade-offs involved, and explain how formal verification with the Certora Prover supports resilience and reliability in a major lending protocol.
Speakers
Topics
From DeFi Security Summit at Devconnect Argentina 2025, hosted by DeFi Security Summit.
Transcript
All right. Finally, uh let's start. You want to give an intro? >> So, I'm Tom Goro from Stor and >> I'm the RSAT. I'm from A Labs. Uh we are a service provider under the AI DAO about a year and a half ago. We put out a proposal and we were selected by the DAO to build the next iteration of a v4. Our talk is about the security blueprint and how we engineered a v4 some new features and some takeaways for your development practices as engineering teams.
So let's start uh what a v4 introduces. So I've I've already talked about I've already taken a scan that everybody knows what uh a is so I think we're familiar with the architecture. one of the major things that we changed with RV4. So as we know that whenever you deploy an RV3 market, it's a standalone market which I which has the liquidity provisioning and borrowing strategy uh compiled together. One of the major architectural changes with AV4 is that uh it makes this architecture more modular by splitting the liquidity provisioning and borrow strategy in two components called the hub and the spoke.
But why do we need this a new architecture? While developing uh while seeing the evolution of a v3 and seeing where it has reached today, we realized that um a v3 for example right now only supports tokenized assets and it's very hard to bring more asset classes into the mix. By separating the liquidity provisioning part, you can have uh more exotic asset classes in a in a much simpler manner because the architecture is very plugandplay. You can plug any hub to any spoke essentially. So for example, you can collateralize your LP position on unis swap while it's earning LP fees or you can connect to another liquidity provisioning infrastructure which is built by somebody else it
doesn't it just needs to follow the interface. That's all. Another key aspect of this new architecture is that when new markets come about for example as we see um let's say that the standard spoke is what RV4 has built which is an RV3 borrow uh uh borrow market whenever new asset classes come into play when they've legitimized and they've gained some traction like in RWAs uh real world assets and users want access to that right now we have to spin up the market from scratch and bootstrap the liquidity uh from zero. But with av4, they can just get a normal credit line. The the users from another spoke get exposure to this new um asset class and can enjoy um
good properties. The first component, the hub, is the central liquidity source. It's an extremely simple contract. It's supposed to be as extensible and modular as possible. The idea is that it only tracks the total supplied, the total borrowed, and the total owed assets. and it does not try to do anything else. When we have a spoke, the idea is this is where users shop for different borrowing terms and it doesn't necessarily need to be a lending market. It can be uh any kind of exotic things that can access and use deep liquidity some of which we'll see in a while.
What's to come in the talk? We're going to talk about uh risk premiums and how we implemented something which most lending protocols don't uh which is variable interest rates for each borrower position. We're going to see why this is important. Uh what are the design challenges that we faced while building this and how how we fixed it. Then we're going to introduce a new paradigm that we uh learned during the development of a v4 which is called proverdriven development. uh we're going to talk about how this accelerated the development of V4 and um some tips apart from this as well.
One thing in most lending protocols in a v3 and a v3 is let's say for example you and I we're both opening a position of the same value by borrowing go I back my position by using a collateral like we talked about that now we have different we can bring different asset classes into the system let's say that I'm borrowing against an LP token tokenized and you're borrowing against ETH the same value in a v3 and in most lending protocols you and I pay the same uh borrow on our loan. But that doesn't seem fair because your token ETH has no risk attached to it. Has less risk than my collateral because my collateral has an additional smart contract risk has an
additional pricing risk for example. But you and I are both paying the same rate. So I think something's wrong. I think someone's someone's getting screwed here because you're basically you're basically paying for my risk which is not fair. So in a v3 what we didn't introduce is risk premiums. It's a new feature where borrowers who back their loans with riskier collateral pay a higher rate pay a higher premium. What this enables us to do is that from before a higher base rate the base rate goes down and if you have some exotic collateral which has more risk or more implied volatility uh risk managers can define a particular risk for it and you pay an additional premium. This essentially incentivizes uh borrowers to
back their loans with less risky collateral because uh they pay less and as you can see the base rate for ETH went down. Earlier it was uh paying for the risk for somebody from somebody else because the the go of suppliers they were still getting a risk average return. So they were fine but not the person borrowing from ETH. And this is good for so this is good for suppliers because risky positions pay more so they earn a higher yield. So risk premiums help us precisely price risk.
>> Thank you. So uh so how can you do this? How can we precisely tailor a borrow position rate specifically for each user? So they have different rates when as riskier the collateral goes. So one way to do it is to use let's say the base rate is 5% that's an example 5% base rate and 1,00 go at that and let's say the risk uh collateral risk is 40% which is just a number that the risk managers determine that this is the risk that collateral brings we can have the effective rate of the b will be 7% which is basically 5% times 1.4 four extra 40%. And now the effective rate is 7%. Which means that
after a year we will pay 70 go in interest which is 50 interest and then extra 20 in fees. Um so let's see how it works for a couple of users because we need at the end we need the hub to be able to extrapolate what is the total amount that user owe to the hub so we can determine how much he owes to the LPS. So h let's say Alice has 1,00 go debt with 10% risk and Bob has 2,000 go debt with 30% risk. We need to calculate the weighted average of those two users because they are the total users in this example. H we need to know what is the weighted average of them to to allow the hub to extrapolate what is the amount that a user owes to it and what he owes to the rest. So we just take Alice
balance time Alice risk plus Bob's balance times Bob's risk divide by the total of debt that exists and we get 23.33% which is the weighted average. This is not precise. There is rounding here because of this division. We could round up or down. If we round up we'll pro overpromise um to the LPS and if we round down we underpromise. So it's better to round down and round against the user in a way and then we don't overpromise and we're still solvent. So let's see what happens if we remove Alice from the system by repaying. So if Alice repays, we just need to remove her from the weighted average, which basically means that we take the total debt times the the old total debt times the old weighted average. Then we
subtract Alice debt times Alice risk divide by the new total, which basically turns out it's 29.99 and it's not 30. Why? Why should it be 30? It's because Bob is now the only user of the system which means that the weighted average of the system should be Bob but Bob risk premium risk credit risk is 30% is 29.99%. It looks negligible but every time we do do operation with an operation this will compound every time it will be less and less precise. So this is wrong.
So what went wrong the division what as I said once we divide as everyone knows when divide we have rounding either round up or round or round up or down. So if we just didn't have this division everything would be precise. So of course we just remove the division and then everything should work. But it's hard because the weighted average is a very intuitive way to do this because we have the weighted average of all of the users together just multiply and and then we have the numbers we want. How can we do it in a different way? We just need to rephrase the problem. Instead of adding the percentage of risk to the interest, we just add the percent of risk to the amount. Basically, instead everyone has the same the same base interest. From before it was like 5%
base and different amounts. So the effective rate is higher but the real rate is the same just the amount is different. Let's see. Let's see the same example as before with one user. So same base rate 5% same um base debt which is one 10 1 go and 40% risk collateral. Now instead of 7% effective rate which is again 5%* 1.4 four extra 40% is seven. We just have the same base 1,00 go with 5% interest and we have extra 400 uh premium ghost debt which basically with the same 5%. Which is basically a debt that we only pay interest for. We don't pay the principal which means that after
a year again we have 50 from the interest and extra 20 from the 400 premium debt. 20 is like 5% of the 400. So it's the same 5% for everyone. Same rate but different effective rate. And let's see what happens with the two users from before. So we have again Alice and Bob. 1,000 go for Alice 10% and 2,000 um um go for Bob with 30%. Instead of doing the weighted average with the division and everything, we just sum everything up. We take one 100 premium debt for Alice and 600 premium debt for Bob which is basically um just the the debt times the risk and we sum
everything up and we have this exact total. We didn't have divisions here. That's why it's precise. Now when Alice repays our debt like before, we just subtract Alice position from the totals. We don't need to divide. We don't need to multiply. That's why everything is precise. You can see that uh 700 minus 100 uh is 600 which is the premium uh go premium debt uh which is basically exactly what Bob has. So now the hub state is like Bob state exactly. So now it's precise. Um I think that made sense. Let's continue with the security practices that we learned during the development of a v4. So before we start there's something that as developers I really
want to stress um you should get involved with auditors at as early as possible in your u whenever you start designing a new protocol. We got involved with Sattorra at the design stage and one of the major things that we did was we started defining properties very early on. Essentially before we got too attached to our code as developers because we spend so much time on things. We start to get a tunnel vision of sorts when it comes to defining what we want. For example, let's say that you start out with the goal of making a circle and while you're developing you realize, okay, there are certain things that are inhibited by um the development by implementation details or something else. Maybe the goal changed, maybe requirements change
from somebody else. Midway you realize, oh well actually I need a triangle. Now you have two options at this time. Either you can power through, you continue or you change. If you power through and you continue, you start molding it into something it may not be or even if it comes out to that, you start applying patches. It may work, but at that point, you're just fixing things. You're not building things. And what this means is that as you start making patches, there could be gaping holes in your system that were missed by the auditors or by yourself because you spent so much time on just thinking about this. Another approach that you could take is instead of fixing you start changing things. You start from
the bottom up and you start with the with the learnings from the previous time invested. You start building uh from scratch. >> Yeah, thank you. Um so basically uh to rephrase what said is that we first need to know what we want to do which is for and in this example is a learning protocol uh with risk premiums. uh and then and then we can think about the properties we want to have um to to make it safe. So we need to to at the start we need to do the design properties let's call it when you know what we want to do which is for example here in landing protocol that protocol is solvent and then when when you want to know how you want to do it when you try to implement when you try to design or
try to plan your implementation you see how you want to do it and then you can think about properties of um of implementation specific properties like some variable should not be zero should not be like any kind of different properties regarding the specific implement mentation. H once you have these two uh two critical times in the start when you know what you want to do and then the middle when you know how you want to do it then you want to form you write it in English and then you want to formalize um your properties in CVS auto verification language which basically helps the our prover to translate your English into mathematical formulas and now we can know uh if uh your code is correct or not and this process as Dario said is very iterative because maybe during development we
discover that what we want to develop is too hard impossible possible or just um just not what market they want, not what the business wants. We talk with them and then they decide they want something else. We can we can change things when we can rediscover what we want and what and how we want to do it. But when you when we do it, we need to explicitly do it. We can't just think in our head we have some one thing and then do something else. So that's why every time you change your mind, you need to rephrase the properties, rephrase the behavior you want to have and that's okay. that that's completely like that's great even because you're developing you're making new new ground and and new ideas and and the prover can help us find both the design issues and
implementation issues as long as you formalize your properties correctly. So now let's go to the most important property uh that we prove for the hub which sher doesn't go down um for this this property basically means that the protocol is solvent. So of course everyone wants all of the protocols will be solvent. Um everyone wants to be solvent and this definition is very hard because protocol solveny it has a couple of different meanings depending on the protocol. For example, if we have a protocol like AV3, it has index index based approach, which basically means that the amount of liabilities the protocol has is the amount of shares that exist times the index uh the supply index in NVC for example and that is the total liabilities the protocol owe to
the LPS and the amount of assets that the protocol has is the total debt plus liquidity and we just need the assets cover the liabilities that's very easy it's very easy to formalize the property it's very easy to check it and if for example I add this malicious function just steals steal money from the protocol. For example, I can just call the function take out teleol all of the money away. You could immediately notice that the property will fail because the assets will go down, the liabilities won't go down and that means that we just lost money and the property will be violated. But in V4 for example we don't use index we use share rate and share rate is just take the total assets divide by total shares and that is the supply share rate uh for the user and
because of this definition the previous property as I described it is true is just true always because if we have this magic magic uh function just steal all of the money from the protocol now we have zero assets basically to calculate recalculate the share rate it will be zero total assets divide by total asset which is zero because we stole thing divide by amount of shares is zero because 0 divided by something is zero and then the obligation the liability of the protocol is zero. So total asset is zero. The liability of the protocol is zero and that's true but but money got stolen. So that's bad. It means that we didn't check what we really wanted to check. What we want to check here is that charet cannot go down because if share go if share goes down it means
that someone took more assets from the protocol than what he uh redeemed in shares or just got free assets because he just stole money from the protocol and share it going down means that someone stole your funds. If share it go up it mean you profit. Share it go down it means someone stole and you got socialized and cut part of the loss all of the loss if if you have a lot of shares. Um and that's what we proved. We prove the char cannot go down which means that the hub is always solvent. No matter uh what kind of spoke we will build and and what logic it will do. The sheret cannot go down always. The hub does all of the check to promise that the hub is always solvent.
During the development of a before as we've talked about you need to write start writing your properties early on. One of the benefits of that is once you've developed such a modular and extensible uh architecture and a protocol these properties come very handy as we know um the hub can connect to any kinds of spokes any exotic borrowing strategies it actually not even borrowing strategies anything that can do something with liquidity essentially now that we have the hub properties written in tinkering and experimenting with new kinds of spoke designs is extremely easy and straightforward because you type out your hub property uh your spoke you can test it against the implementation very soon and find out if it's compatible and if it does not break any core invariance
of the protocol because you just need to adhere to the hub interface and run the sedor approver once this way you can test and tinker with your ideas and accelerate your development uh quite fast one thing we also learned during the development was we had multiple iterations where we tried a lot of different ideas to make different kinds of features work most of them are not covered here but you can check out other talks or our blog posts for that we should you should start writing um your protocols as prototypes so that you can iterate on them and uh work on them faster. Another tip that I have is also consider using so as we know that the set approver um is a symbolic engine um consider using lighter SMTS like Z3 such
that you can script and type out smaller parts of your code u faster like maybe you have some you're doing some extrapolation uh on the hub or on on some level and you want to figure out if these roundings work after thinking about whether they're in the favor of the protocol or not. Uh really quickly to uh conclude um our V4 because of the secure development opens up a lot of design space and some examples could be that like we've talked about uh you can collateralize LP positions. One more is that because of the way that risk premiums work they're very modular and extensible. You they can be built not just on your collateral uh because the current market works just
like a V3 market. They can work on your entire position uh like an options market where your risk premium is sort of exa exactly equivalent to a margin for example. Um that's all from our side. Our V4 code is live. Check out the properties. Uh thank you so much. >> Thank you. [applause and music] >> Thank you guys. Am I breathing?