Cyfrin Updraft: Rocket Pool rETH Integration Full Course

Cyfrin Updraft Courses · 2:52:26

Tasuku Nakamura, founder of smartcontract.engineer and a smart contract educator, teaches developers to integrate Rocket Pool rETH into DeFi applications. The course works through exchange-rate calculations, acquisition and redemption, liquidity, NAV oracles and restaking, with Solidity exercises involving Aave, Balancer, Aura and EigenLayer. It assumes Solidity and advanced Foundry experience.

Speakers

Topics

From Cyfrin Updraft Courses, hosted by Cyfrin.

Transcript

Welcome to the course for rocketpool re integration. This course is for advanced solidity developers who have experience with foundry. We expect that you have experience writing foundry test and then executing the test against the main network. And we also expect that you have some basic knowledge of defi. For example, if I mention something like web or amm I expect that you know what they are. In this course, you'll learn about the re architecture. some of the contracts that interact with the RE token contract. You also learn about R E to TOE exchange rate, some math and some examples, and we also have some foundry exercises. Furthermore, you'll learn how to use flash loans to create a leveraged position for R E. Here, I'll explain

what leverage is and how to use flash loans to create a leveraged position. The course is focused on integrating R E into other smart contracts and other D5 protocols. some of the example integrations that we'll go through. You'll get some experience working with a B3, Balancer B2, and IGEN layer. Why should you take the course? Well, you'll get some ideas on how to integrate R E into your smart contracts. You also gain tons of experience with other D5 protocol. And finally, if you're into audits and bug bounties, here you'll get some experience with the most famous D5 protocols. So, the experience and the knowledge that you pick up here might help you in your audit or bug bounties.

This course will have some exercises in Foundry. So here I want to explain how to set up for the exercises. The first step is to navigate to a GitHub repo called dyre and then you'll need to get clone this repo. To get clone this repo, click on the code and click on this getgithub.com URL. And then inside your terminal, you'll need to type get clone followed by this URL. Once you get clone the repo, use your favorite code editor to open this repo and then click on read me. Here I'm going to show you how to set up Foundry so that you can do the exercises. The first step is to go to Foundry. So open your terminal and then cd into Foundry. cd Foundry. Once you're inside the Foundry folder, build a project by typing forge build. This

should compile all of your contracts and install any dependencies. There's one other step that you'll need to do inside this Foundry folder. The exercises will execute against the main network. So you'll need to provide a mainet fork RPC URL. I have the mainet fork URL stored in a file called M. So going back to our code editor, clicking on Foundry here, you can see a file called M. To do the exercise, all you need to do is fill out this fork URL. And then when you execute the forge test, set this fork URL as the environment variable. The rest of the environment variables that you see over here are used to run Forge scripts. This is an optional setting. Next, I'm going to explain about the folder structure

for the exercises. On the foundry and on the source, you'll see two folders that will interest you. Exercises and solutions. Exercises will contain incomplete code where you will write your code and then execute the test. So, for example, if you look at the test, you'll see that these tests are executed with the contracts from the exercises folder. However, if you're feeling stuck or maybe you just want to see the solutions, then there's two things you can do. You can click on the solutions to see the actual solutions or if you want to run the test against the solutions, then change the file path.

Change the file path from exercises to solutions and then execute the test. To do the exercises, I'm back inside the GitHub repo D5 ref and then click on the readme file. There will be sections where it says foundry exercises. For example, let's click on one of this foundry exercise to add liquidity to a balancer. and this will take you to another readme file where it will instruct you on what to do for the exercise. After you've completed the code and you're ready to test, go ahead and copy the test command and then execute it inside your terminal. When you do so, make sure that you set the fork URL as an environment variable. The full version of this course is available on siphon updraft. Follow the course on Siphon Updraft for better tracking

quizzes, prove your knowledge, and join a community of over 50,000 web 3 engineers ready to help you out and answer your questions. Let's start with a quick overview of how ETH staking works. And by doing so, you'll see what limits regular users from running their own validator and directly staking into the ETH network. This will also give us a good understanding of what problem rocket pool solves. So the purpose of ETH staking is to run validators, secure the network and earn ETH rewards. The requirement to run a ETH validator is that you'll need 32 E to stake into the network. Prepare the validator key and the withdrawal key. And then you also need some technical skills to run the valator. So let's say that Alice has 32

ES. She also has a technical skills to generate a withdrawal key, a val key, and also store these keys in a secure manner. With her 32 ETH, she wants to run a validator and secure the ETH network and earn some ETH rewards. The first step is to stake her 32 ETH. She does this by sending a transaction to a deposit contract, sending her 32 E, and the validator public key, which is derived from her validator key, and her withdrawal credentials, which is derived from her withdrawal key. The withdrawal key is later used when she wants to unstake her 32E. Next, she will run a validator. The validator key is used by the validator to assign blocks and attest to transactions. So, she'll need

to take this validator key and then stick it inside this server that runs the validator software. And this is a quick overview of how ETH staking works. Now, you can already see that for Alice to become a ETH staker, she first needs 32 E. Let's say that one E is $3,000. Then 32 E is $96,000. That's a lot of money. So that's the capital requirement that Alice will need and she also needs some technical skills to be able to run a valator and secure the valator keys and her withdrawal key. In the previous video, we saw the limitation for directly staking into the ETH network.

In this video, I'll explain how RocketPool overcome these problems. Let's begin by answering the question, what is Rocketpool? Rocketpool is a decentralized ETH staking protocol. Remember in the previous video we saw Alice become a staker into the ETH network but there were some limitations. These limitations are solved by the rocket pool in a decentralized manner. As a quick review, the problem that we saw with solo staking ETH is that we needed 32 ETH and we also needed the technical skills to run a validator and secure the keys. If you lack the capital requirement or the technical skill, then you cannot become a ETH staker. But what Rocket Pool allows a user is that you don't need 32 ETH and you also don't

need the technical skills to stake into Ethereum and earn some rewards. For example, let's say that Alice is a staker with one ETH and no technical skills. Linus is a node operator. He has the technical skills to run a server, secure the valator key, and the withdrawal key. However, he only has 18. And again, to become a solo staker, you need 32 E. So Lennis is backing 24 E to become a B later. Then let's say that we have Whale who has 320 E but without any technical skills. All three of these users cannot become a solo staker in the ETH network. Alice lacks the capital requirement and the technical skills.

Linus lacks the capital requirement and Whale lacks the technical skills. However, under the RocketPole protocol, all three users can join into the Ethereum network as stakers. The way it works is that all three of these users will interact with the rocket pool contracts. Alice will deposit one ETH, Minis will deposit a ETH and also register as a node operator. Whale will simply deposit 320 ETH. Now, remember that to become a validator in the ETH network, you need a multiple of 32 ETH. The rocket protocol will match all of these ETH that was deposited, the one E, the 8 E, and the 320 E that was all sent to the rocket pool contracts. So now

this rocket pool contract has more than 32 E. And now Linus can register as a validator within the rocket pool protocol to become a validator. Now here instead of running the ETH validator software, Linux will have to run a rocketpool software. This rocket pull software will interact with the ETH network to earn ETH staking rewards. This ETH staking rewards will be split among Alice, Linus and Whale, the stakers and the node operators. So this is how Rocketpool is able to match different users with different resources so that all of them can join the Ethereum network and participate in staking and earn the staking rewards.

What is RE? R E is a liquid staking token that is issued by the Rocket pool. There's two ways to obtain RE. The first way is to mint R E by directly depositing E into the Rocket Pool protocol. Now, for you to be able to do this, minting must be enabled by the Rocket Pool protocol. The other way to obtain RE is by a decentralized exchange. You can swap any tokens to buy R E. Let's look at example of the first way directly minting R E from the Rocket Bowl contracts. Let's say that Alice deposits one E into the rocket pool contracts. In return, let's say that she gets back 0.83 R E. Now notice that she deposited one E but she only got back 0.83 R E. The exchange rate is not 1

one. This is because R E is a yield bearing token. It acrrues value. Assuming that the rocket pool protocol is doing well and the node operators of the rocket pool are performing well then over time this R E is going to collect E staking rewards. Hence it occurs value. It is yield bearing and that is why when Alice deposits one E she gets back less of R E. If she wants to redeem ETH from her re then she would send this re back over to the rocket bowl contracts and hopefully she'll get back more than one E. The other way to obtain R E is through decentralized exchanges such as Curb, Unis swap, and Balancer. For example, let's say that Joe has one E

and he swaps this one E with a decentralized exchange and he gets back, let's say, 0.82 RE. Now, when Joe does this, he'll need to keep in mind that there is some trading fee. So, he might get less R E than if he was to mint directly with the Rocket Bull contracts. Depending on the market condition, this might flip. Joe might have a better exchange rate if he were to obtain REF through a decentralized exchange instead of directly minting RE from the Rocket Pole contract. So these are two ways to obtain AR directly from the Rocket Pole contract and from decentralized exchanges. The value of REF generally increases over time. And we saw this in the previous example where Alice

directly deposited one E into the Rocket Bowl contracts and she got back 0.83 RE. The exchange rate wasn't one to one. And this is because R E is usually more valuable than E. But why is it that generally R E is more valuable than E? The reason is R E increases relative to E because it accumulates staking rewards. Of course, if the node operators of the rocket pool are penalized for some kind of misbehavior, then the value of re can decrease relative to E. So assuming that the node operators of the rocket pool are performing well then re will increase relative to E. Let's plot this on a graph and see visually how the value of

R increases relative to the value of E. Let's start with definition. We'll say that the exchange rate of E per R is the amount of E backing one R E. So for example one R E might be worth 1.2 E. Let's now plot this on a graph. On the vertical axis, we'll plot the exchange rate. The exchange rate of 1 R E to ETH. And then on the horizontal axis, we'll plot time. Here, time moves from left to right. And now, assuming that the value of RE increases relative to the value of E. Here's what the graph will look like.

Over time, the value of RE increases. And you also notice that the value of RE is not a straight line going up. Instead, it looks like a stair that would jump up and then it'll be flat for a while and then it will jump up again. It looks like a stair. The reason is when the rocket pull protocol updates its exchange rate, you'll see the value of reced. Rocketpole re is a nonrebase token. But what does that mean? So in this video, I'll explain the difference between a rebase and a nonrebase token. example we'll be using in this video for the rebase token will be the lido sde and for the non-rebase token we'll look at rocket pole re okay so let's start with ebase token lido sde rebase token

means that the token supply and the balances change algorithmically inside the token contract there is some kind of algorithm that determines the supply and each user's balance of the token for example let's say that inside the token contract the token supply grows linearly over time so what you might see is that over time without any user interaction the token supply will increase and then maybe there's some kind of user interaction that burns the token so the token supply goes down and then without any user interaction again the token supply increases linearly basically the token supply and the token balance of users change over time without any user interaction that's what rebase token is so for example let's say that a user has one SD saf allows users to redeem EH

one to one. So if you had one ST, then you can redeem it for one E. Now let's say that some time has passed and this user's token balance, this user's ST token balance has increased to 1.1. And this happens without any user interaction with the token contract. Since this is a rebase token, the supply in the token balance is determined by the algorithm inside the token contract. So let's say that now this user's token balance is 1.1 STE. Again, this user can redeem SD for E at a one to one exchange rate. So, they have 1.1 SD. They'll be able to redeem it for 1.1 E. Okay, so this is a simple example of a rebase

token. Next, let's take a look at a nonrebase token. And for this example, again, we'll be using Rocket Pool RE. Non-rebase token means that the token supply and the token balances of users only change when there's a mint or a burn. So, think about a regular ERC20 token. You have the function mint that will increase the total supply and when the function burn is called the total supply of the token will decrease. And we can see this in a graph over here. The supply let's say is static over time. When some user or some transaction mints new tokens the token supply will increase. And then let's say that there is another transaction that burns some tokens. Then the token supply will decrease. If there is no user

interaction, the token supply and the token balance of users will remain the same. It will be static. Raf acrews value over time. So let's say that in the beginning the user has one re. For simplicity, let's say that the exchange rate of E to E is one. User has one R E. He'll be able to redeem one E. Let's say that some time has passed. The user still has one R E. Since this is a non-rebase token, the token supply and the balances remain static. In this case, this user started out with one re, the token balance of this user remains the same, assuming that this user hasn't minted more re or burnt some of the re as long as the user

holds on to this one re. After some time, this user will still have one re. However, the exchange rate of re will change. Since re generally acres value over time they'll be able to redeem more E for their R E. For example, let's say that the user has one R E and they will be able to redeem 1.1 E. So that's the difference between a rebase and a non-rebase token. Now because of the way the token balances change are different between R E and STE there might be different tax implications. First of all, I'm not a tax expert. So don't take this as a professional advice. So what I say here might not apply to the country that you have to pay taxes to. So with that said, let me comment on the

possible tax implication based on how the token balances change between a rebase token and a nonrebase token. For a rebase token, the token supply increases. So this might be a taxable event, which means that you'll have to declare tax on the increase of ST. And for R E, this is a non-rebase token. Since the token balance of re does not change, this might mean that in the country that you have to pay tax, there is no taxable event here. The token balances are the same. But again, this is not a financial advice. So to be 100% accurate, you'll need to consult with a specialist. Once you have re some of the things that you can do with it is to add liquidity to decentralized exchanges

such as unis, curb, and balancer B2. You can also lend your re to a or you can create a leverage position by first supplying your re as collateral to a and then borrowing a stable coin to buy more re. Another thing that you can do with your re is to restake it on ien layer. Let's take a quick look at the examples that I just mentioned. First, you can add your re as liquidity to a decentralized exchange such as unisaw3. For example, here inside the web browser, I have the UNISOB B3 app open and I'm navigated to the pool for R E/. And then to add liquidity to Unisaw B3, you will click on add liquidity.

Then you will select the pair R E and E, set a custom price range, and make sure that the price range is outside of the current price. Then scroll down, click on continue, and specify the amount of R E to deposit as liquidity. For example, I have 0.038 R E. So I can put 0.0 01 R E and then click on review to proceed with the transaction. Personally, I wouldn't recommend you put R E as liquidity into Uniswap B3. The reason is the value of RE generally increases over time relative to the value of BE. This is because R E acrru the staking rewards. So if you were to add liquidity to unisaw B3, then you're saying that you're willing to sell your RE at a

certain price range, but over time re will grow in value. So to keep up with this increasing value of REF, you'll have to keep on repositioning your liquidity position in Uniswap B3. Otherwise, you're selling your RE at a discount. So if you want to provide liquidity to a decentralized exchange with your RE, then I suggest you deposit your RE into other decentralized exchanges such as Curb and Balancer. So if you wanted to deposit your RE into Curb Finance, then head over to the Curb website, then search for RE. Notice that the TBL of this pool is only $700,000. So, it's a small pool compared to other pools in the decentralized exchanges. However, if you wanted to

proceed on adding liquidity to this pool, click on it and then head over to deposit. And here you'll be able to specify the amount of W and R to provide as liquidity. For example, again I have 0.03847 RE. I can add for example 0.01 RE. Then click on approve spending and then send the transaction to deposit re as liquidity. Now the reason why I suggest you deposit your re as liquidity to curb or balancer over unis swap b3 because both on curb and balancer the exchange rate of re is always updated.

So whenever a trader swaps either on curb or balancer the current exchange rate is fetched from the rocket pool contracts. This is not the case for unis swap v3. Okay. And if you wanted to add liquidity to balancer v2, head over to pools and then find the re pool pool and then click on add liquidity. Specify some amount. Let's say 0.01 re again. And if your wallet's not connected, go ahead and click connect wallet and then proceed with the transaction. Other than providing liquidity to a decentralized exchange, you can also provide our ETH either as collateral or just supply it to a lending market. For example, to a B3. If you simply want to supply it to a lending market and then earn some interest, you can click on supply. Put

your amount in here and proceed with the transaction. And if you wanted to take a leverage position, again, you would click on supply. Let's say 0.01 R E and then proceed with the transaction. You're supplying R E as a collateral. This will give you some borrowing power to borrow some stable coins. So once you supply RF as collateral, you'll be able to borrow any of these coins on the right side. And for example, you will borrow stable coin buy and that is your leveraged position. For the final example, you can also restake your re into layer. Then what does restake mean?

In simple terms, restake means you're staking your tokens to earn more rewards. When we stake ETH into the rocket pool, we get back our ETH, which is giving us some staking rewards in E. Now take this R E and then stick it into layer. By doing so, you'll earn other rewards. This is called reststaking. And to restake on layer, click on restake. Click on the token that you want to restake. For example, let's stake our E. So, I'll click on this and then specify some amount. Let's say 0.01 again. And then click submit to proceed with the transaction. Here I have some amount of our E already staked. And if you look down, you can see some of the rewards that I've earned so far. I've earned less than 0.001 E. And I've also earned

some rewards in IGEN token. So these are some examples of what you can do with R E. Some of the options to obtain R E given that you have E or to redeem EH given that you have R E are to directly use the rocketpool protocol, use the DEX aggregator or any of the decentralized exchanges. And for example, let's say that we have one E. If you were to directly mint our E from the rocket pool protocol, we will get roughly 0.88850 88850 are ETH. Let's compare this number with DEX aggregators and decentralized exchanges on a DEX aggregator like D5 lama swap. Let's say I have one ETH and wanted to find out the best deal to get our E. And at the moment it says that

the best deal is approximately 0.89 R E. Let's see what the exchange rate unis swap B3 will give us. So let's say that we wanted to swap one E. How much R E will we get? And again it says we'll get roughly 0.89. 89023 R E and then on curb put in one W and it will give me 0.89124 R E. So far I think this is the best deal. How about on balancer B2? Put in one W and it will give us 0.89038 R E. So currently the best deal to get RE from WE is on curb. If you want the best deal for your RE, you'll have to do something similar. compare

the exchange rates between different protocols. Here I compare the exchange rates between the rocket pool protocol, DEX aggregator and some decentralized exchanges. This method goes both ways to exchange ETH to re and if you were to exchange from re back to E. It's helpful to understand several rocket pull contracts that the re contract interacts with. Let's start with the rocket pool storage contract. This is a contract that multiple rocket pull contracts have access to. Authorized contracts will be able to write any arbitrary data into this rocket storage contract and any contract will be able to read the data from this rocket storage contract. As an analogy, this is like a database where

only authorized users will be able to write into the database and any user will be able to query the database. To be more specific, let's say that we have the rocket pull contracts and the rocket storage contract. Authorized contracts will be able to write arbitrary data into this rocket storage. For example, they might call the function set address to set some address inside this contract or set and so on. Then they can also get the address that was stored by calling the function get address or get a number that is stored in this contract by calling a function get and so on. When a user deposits ETH and mints re, there are several rocket pool contracts that are called. However, here I want to

highlight three contracts. Rocket deposit pool, rocket storage, and rocket token are E. Let's say that Alice has one E and she deposits this one E into the rocket deposit pool contract. Among many things, the rocket deposit pool contract will get an address from the rocket storage. This will get an address for a contract that is responsible for the protocol settings. And here it's going to check whether deposit is enabled or not. It checks that deposit is enabled and if it is it will call the function mint on the rocket token ref. This is the re token contract. Now the rocket token re contract will call the rocket storage contract so that it can get contracts to query data that is needed to calculate the exchange rate

from E to RE. Once the exchange rate is calculated, it will mint R E to Alice. To redeem E from RE, the user will have to burn their RE. There are multiple contracts that are involved with burning re. But again, here I want to highlight three contracts. Rocket deposit pool contract, rocket token re, and rocket storage. Let's say that Alice has re and she wants to redeem her E. The first thing that she'll do is call the function burn on the rocket token re contract. Once the token is burned, the re contract will have to get addresses by calling into the rocket storage contract. It will get the address for the contracts that are needed to calculate the exchange rate from re back

to E. Now, if there are enough E inside the R E contract, then E will simply be sent back to Alice and we're done here. However, if there's not enough E inside the rocket token R E contract, then it will have to call the function withdraw excess balance on the rocket deposit pool contract. The re contract is asking the rocket deposit pool contract to send some E back to the rocket token re contract. The rocket deposit pool contract will have to get another contract to calculate the excess amount of beef that can be withdrawn. And this is done by calling the function get address on the rocket storage contract.

The rocket storage contract will store the contract address that is responsible for calculating the excess balance that can be withdrawn. And once that is done, ETH is sent from the rocket deposit pool contract over to the R E token contract. And then finally, Eve is sent back to Alice. Here you're looking at the function deposit inside the contract rocket deposit pool. This function is called by the user if they wanted to mint or E. In this video, I want to show you when the function deposit is called, how does it check whether deposit is enabled or not, and also currently there is a deposit fee. So if you're writing an integration contract with the Rocket Pole, you might want to be aware that

currently there's a deposit fee. So first let's see when a user calls the function deposit, how does this contract check whether deposit is enabled or not? The check is done in the first few lines. So let's take a look. First, it gets a contract address from the rocket storage. The contract that it's getting is called rocket dow protocol settings deposit. And the way it gets it is by calling a internal function called get contract address. This function comes from another inherited contract called rocket base. The get contract address function will eventually call a function called get address. And you can see here that it calls the function get address on the rocket storage contract. This is an example of how contracts in the

rocket pool protocol calls into the rocket storage contract. Okay. So going back it gets the contract address of rocket protocol settings deposit. Once it gets this contract it calls a function called get deposit enabled here. This is how this function is checking whether deposit is enabled or not at the protocol level. Okay. Next, let me show you where deposit fee is calculated. Scrolling all the way down, you can see here that there's a variable called deposit fee. And the way it calculates the deposit fee is by first calling the function get deposit fee again on the contract rocket dial protocol settings deposit gets this number multiplies it by message value the amount of beef that was sent by the

user and then divides it by calc base. So what's going on here is it's calculating a percentage of the amount of beef that was sent. This is deposit fee and then from the amount of beef that was sent it will subtract this amount. This is deposit net. The amount of re to mint is based on this deposit net. In the future, this might change. But if you're writing an integration with the rocket pool protocol, currently there is a deposit fee. Depending on the percentage of what deposit fee is, the actual amount of E to calculate the amount of R E to mint may be less than the amount of E that the user sent. The math to calculate the exchange rate for R E and E is simple. Let's say capital E is the total E that is logged inside the

rocket bowl protocol and capital R is a total R E that is minted by the rocket pull protocol and then we have two variables lowerase R which will be the re amount and lowerase E which will be the E amount when we're calculating the exchange rates these are the two variables that we'll be solving for the equation to apply is given by lowerase E is equal to lowerase R / uppercase R multiplied by capital case E. For example, given that you have some amount of R E and you know the total R E supply and the total E that is locked inside the rocket pool protocol. Then putting the numbers in here, you can solve for the amount of E that you will receive.

Let me show you example using actual numbers. Let's say that capital R is 5,000. The total supply of R E is 5,000 and capital E the total amount of E locked in the rocket protocol is 6,000. How much E for one R E? In other words, if I were to burn one R E to redeem E, how much E will I get back? To answer this question, we'll apply this equation and then solve for E. And we already know what all of the values are. So we have capital R which is equal to 5,000 and we also know what lowerase R is.

Lowerase R is 1 since here we have one R E. So this will be a one and we also know what capital E is total E locked in the rocket pole protocol. This is 6,000 and this is what we get. Simplify this and we get this is equal to 1.2 to E. When the rocket protocol has 5,000 re and total E is 6,000 and if we were to redeem one R E, then we will get back 1.2 E. Next, let's ask the question in the opposite direction. Given that we have one E, how much R E will we get back? To answer this question, we start

with this equation again. And this time instead of solving for lowerase E, we'll need to solve for lowerase R. We multiply both side of the equation so that the R will come over here and divide both side of the equation by capital E so that the E will come over here. And this is the equation for lowerase R. Let's bring this over to the right side. And now we're ready to plug in the numbers. Let's start with lowerase E. lowerase E is equal to 1 since over here it says 1 E. How about uppercase R? Upperase R is equal to 5,000 and then uppercase E is equal to 6,000. Okay, so we have the expression 1

* 5,000 / 6,000. Plug this into a calculator and you'll get an approximate answer 0.8333 R E. If we were to put in one E when the R E supply is 5,000, E supply is 6,000, we'll get approximately 0.8333 R E. Next, I'm going to make some few comments about the contract rocket token R E. This is the re token contract. The three things that I want to comment on here is on the function mint and on the function burn and their exchange rates. And finally, there's also a transfer before hook which checks that there is some kind of block delay before a transfer can happen. Okay, so let's start with the function mint. The

function mint can only be called by authorized contract. This authorized contract must be the rocket deposit pool contract. And then it calculates the amount of re to mint by calling the function get re. We'll come back to this later. Now moving on to the function burn. This function can be called by anyone burn there are e and they can redeem the e. The way it calculates the amount of e to give back to this user is by calling the function get e value. So these are two functions that calculate the exchange rates between our e and e.

The function get our e value and the function get e value. So now let's take a look at these two functions. So it's going up. Okay. So here they are the function get E if value and the function get our E value. And here I want to highlight two things. The first thing is how it gets another contract. So here you can see that the function get contract address which we've discussed in the previous video. And this function will eventually call the function get address on the rocket storage contract. Here it's getting a contract called rocket network balances. Once it does that, it queries for the total E balance locked inside the protocol and the total re supply. Once these two numbers are fetched, then it use the calculation

that we discussed that the amount of E to mint is given by the amount of RE that was provided multiply by the total E divided by the total supply of RE. You'll see a similar pattern with the function get RE value as well. What this function will do is it will calculate the amount of re to mint to a user given the amount of e that they provided. And again the equation follows the amount of re to mint will be equal to the amount of e that was given by the user multiply by the total supply of re divided by the total e locked in the protocol. And these two values again are query by getting the contract rocket network balances from the rocket storage and then calling the function get total e balance and get total re supply. Okay,

the final comment I want to make is on the transfer hook. So at the bottom you see that there's a hook called before token transfer. If from is not equal to address z. If this is not a mint, if this is a regular transfer, then there is a block delay before another transfer can happen. And you can see this check over here. Block passed must be greater than deposit delay. So to clarify, this isn't a block delay on all transfers. So let's dig a little bit deeper inside this code to see what the condition is for the block delay. The first thing to note here is that inside the comment, it says check which block the user's last deposit was. The way it does this is it first computes the key to get from the rocket storage contract. call the

function get you in to get the last deposit block and then it will get the configuration for the deposit delay and then it checks that the current block minus the last block this user deposited is greater than the deposit delay that is stored inside the protocol settings. So as you can see this block delay does not apply to all transfers. It only applies to the last block that the user deposited and this information is stored inside the key user.block dotb block inside the rocket storage contract. Let's search inside this rocket pull repo to see where this might be stored.

Search for this keyword and you can see over here that it only appears inside this contract. So for now there is no block delay after the last time the user deposited. However, this might change in the future. So if you're writing a contract that integrates with the re contract then you should be aware of this. The reason why the deposit delay exists is for a historical reason. Currently, it is not used since its functionality is replaced by the mint fee. However, the code still remains inside this contract because the re contract is an immutable contract. Some ERC20 tokens are upgradable. However, for re contract, it is not upgradeable.

This code cannot be changed. Therefore, although the deposit block is no longer used, it still exists inside the code. To calculate the amount of re that you will receive for putting in some amount of ETH and also to calculate the amount of fee that is taken out from this E amount, we'll need to do two things. Get the protocol settings for the deposit fee. Do some calculation and then call into the re contract to calculate the amount of re that we will receive. Let's start with the first part of getting the protocol settings for the deposit fee. deposit fee is equal to protocol settings dot get deposit fee. Next, let's calculate the fee. This deposit fee will represent a percentage when we

divide by the calc base 118. So, we multiply the amount of E if amount by this deposit fee and then divide by calc base. E is equal to E amount multiply by deposit fee divided by calc base. And then the amount of R if that you will receive is calculated by deducting this fee. Say if amount minus equals fee and then we call the function ref.get if value passing in this if amount where the fee is already deducted. Okay. And then let's assign this to the variable that is returned. R if amount is equal to. Okay. Let's execute the test. So here's the command

forge test with the fork URL and the test file will be exercise swap rocketpool.soul and the name of the test that we're going to execute is called test calc to ref. The test passed. Let's look at the logs. The exchange rate of one R E is roughly 1.12 E. And for putting in one E, we roughly get back 0.888 R E. And here's a deposit fee. The function calc ref to e will calculate the amount of e that we will receive given the r e amount. The solution will be one line of code. So let's assign this return value e amount. The amount of e that you'll receive. The function that we'll need to call is

ref.get if value and then passing in the amount of r if r if amount. To test your code, run the command forge test with fork URL. The path for the test will be exercises swap rocket bull. So, and the name of the test is called test calc to E. And the test passes. For putting in re, you'll approximately get 1.125 E. Minting re can be disabled by the protocol. How can we check if the protocol is currently allowing minting of re or not? To check whether minting is enabled or not, we'll need to call the contract protocol settings and then call the function get deposit enabled.

And to get the maximum deposit amount, we'll call the contract deposit pool and then call the function get maximum deposit amount. Okay, let's return this. Say return and then inside the terminal, I'll execute this test command. The file is exercise swap rocket pool and the function that will test the function get availability is called test get availability. The test passes. Deposit is currently enabled. And the maximum deposit is approximately 2.425 with 22 decimals. The protocol setting for deposit delay is stored inside a rocket storage contract. So we need to call our storage the contract

rocket storage.get get you in and then inside here we'll need to pass in the key. So let's see what key we need to pass in here inside the rocket token re contract and inside the function before token transfer it shows us how to get the deposit delay. The way it gets the deposit delay is this line of code. So the key is inside here. So I'm going to copy this and then paste it over to my code editor. Okay, here it is. Let's test our code against the test. Here's the command to test the function get deposit delay. The test file is located under exercise swap rocket pool. And the function that we're going to execute to test the function get deposit delay is called test get deposit

delay. Okay. And our test passed. To get the last block that the user deposited again we'll need to call the contract rocket storage. Say return r storage.get. Here we'll need to figure out what key we need to pass in. We can find this by looking at the re contract inside the re contract and inside the function before token transfer. We can see over here that this line of code gets the last block that the user deposited and the code to compute the key is above this line. Let's copy this and then paste it in here and change this from to user. Okay, let's execute the test. The function that we're testing is called test get mass deposit

block and a test passed. To swap E to ref, we'll need to call the contract deposit pool and then call the function deposit. Deposit pool dot call the function deposit. We also need to send E if to mint our E. Say value. Send all of the E that was sent into this contract. Message value. That completes this exercise. Let's execute the test. The file that we're testing is exercise swap rocketpool and the name of the test is test swap E to ref. The test passed. Let's take a look at the logs. For putting in one E, we get approximately 0.8883 R E. To swap R E back to E, we'll

need to call the function burn on the re contract. Essentially, we're burning our RE. And to burn the reef, we first need to point the re into this contract from message sender. So let's say re transfer from from message sender to this contract address this further amount R amount. And then we need to call the function burn on the re contract. R burn further amount R E amount. This will burn the re and then send E back into this contract. For this contract to receive the E, let's declare a payable receive function receive external payable and then execute the test

command. The test file is exercise swap rocketpool and the function that we're calling to test our function swap R E to E is test swap R E to E. Okay, the test pass test. Let's go over the solution for how to swap web into re using unis swap b3. Here you don't have to do much since there's already an internal function that will handle the swap with unis swap b3. So all we have to do is make sure that we pass in the correct parameters into this internal function. The parameters to pass are token in token out fee and these three parameters will identify the pool amount in amount out min and the receiver. Okay. So over here later we'll call that internal

function swap. But before we can do that we first need to pull the W into this contract from message sender and then approve the UNISAW B3 router to pull this W from this contract. So first let's pull the W from message sender. W dot transfer from message sender into this contract address this for the amount web amount in and then next we'll approve the unis swap b3 router to pull web from this contract over to the router web dot approve address of the router for the amount web amount in and then call the internal function swap the first input is token in token in with

token now is re and the fee that identifies the pool is declared over here. It's imported from the constants unisoft B3 pool fee ref. I'll copy this, scroll down and then paste it here. Okay. Next is amount in amount in. Next is min amount out. This is re amount out min. And the last parameter is a receiver of re address this. Okay, let's execute the test. The command to execute the test is forge test forkl with the forkl from the environment variable. The file is called exercise swap unis swap b3 and the function that we're going to call is called test swap web to ref. The

test passes and for swapping one to re we get back approximately 0.891 re. Let's go over the solution for how to swap our E back into E using Uniswap B3. Again, we'll call the internal function swap, which will handle the details of how to interact with Unisoft B3. All we have to do is pass in the correct parameters into this internal function. The parameters are token in, token out, fee, amount in, amount out, min, and the receiver. Swapping R E back to F. We'll first need to pull ref from message sender into this contract and then approve the unisoft b3 to spend the re from this contract. So type re transfer

from message sender into this contract for the amount re amount. Next we'll approve the unisoft b3 router. approve address of router for the amount re if amount and then call the internal function swap. Token in is re if token out is web. The pool feed that identifies the pool is a constant that is imported at the top of the file. So we'll go there and then copy this. Go back down paste it. Next will be amount in r e if amount in. Next will be amount out. This is amount out min and the

receiver of web address. This that completes the code. Let's execute the test. Here's a test command. The test file is exercise swap unis swabb. And the function that we're going to call is test swap ref to ref. and we get back approximately 1.120 W. Let's swap W to R using balancer. The solution will be simple since there's already an internal function that will handle the swap between balancer. So all we have to do is make sure that we pass in the correct parameters token in token out amount in amount out min and the pool ID that identifies the pool. This pool ID is also imported at the top of the file and

it is called balancer pool id re. So to swap we to re we first need to pull in web approve balancer to spend this web and then we'll call the internal function swap say web dot transfer from message sender to this contract for the amount web amount in. Next, we approve the balancer contract web.approved. The contract that's going to execute the swap is called a vault. Address vault. Amount of W that this vault can spend will be W amount in. And then call the internal function swap.

Token in will be W. Token out will be R E. Amount of token in will be W amount in. Minimum amount of R we expect to get back will be R E if amount out min. and the pool ID. Let's go back to the top of the file, copy this balancer pool ID constant. Go back down and then paste it here. Okay, let's execute the test inside the terminal. This is the test command that I will execute. The file is called exercise swap balancer v2. And the name of the function that we're going to execute is called test swap web to our E. Okay, our test pass. And this is the amount of R E that you'll get for putting in one E. The solution for

swapping R E back to F using balancer follows a similar pattern to what we saw in the previous solution when we swap from W to RE. So first I'll copy this code and then paste it here. And the first thing that I'll do is change to re since we're pulling in re into this contract from message sender and then approving the bulk contract to spend. Then next I'm going to change this amount in to re if amount. Then lastly we'll change the parameters around when we're calling the internal function swap. The token in will be re token out will be ref amount in will be r e if amount in and minimum

amount out will be ref amount out and the pull ID will be the same. Okay, let's run the test. Execute the forge test command. The file is called exercise swap balancer B2 and the function that we're going to execute is called test swap re to web. The test passed. Let's take a look at the logs. For swapping one R E to W, we get approximately 1.12 W. What we're going to be building is a smart contract that will do flash leverage with R E on AB. Before we can build this smart contract, I'll first explain what AB is and what leverages. AB is a decentralized protocol that allows users to get over collateralized loans. The protocol

involves two types of users, supplier and the borrower. The supplier will supply a token to the AB protocol to earn some interest. For example, this user has supplied D to the A protocol. This user's D will be earning interest. On the other side, we have the borrower. Let's say that this user wants to borrow the die that the supplier supplied. To do this, you'll need to get a over collateralized loan. The first step for this user is to deposit a collateral. For example, this user supplies ETH as collateral. And now this user can borrow tokens inside the aby protocol. For example, borrow D. Now there's a limit to the amount of token that this user can borrow. The amount that they can borrow must be less than the amount of collateral that they supplied. Hence,

this is called the over collateralized loan. For example, if this user provided one E and one E is equal to $1,000. And for simplicity, let's also say that D is $1. So the amount of D that this user can borrow will be less than $1,000. The specific amount of tokens that this user can borrow from the AB protocol will depend on the protocol settings for the collateral that was deposited. The borrow tokens will acrue interest. So when this user decides to repay the amount of tokens that they borrow, they'll have to pay the amount that they borrowed, the principal, plus the interest that accured on the amount of tokens that they borrow. The part of the interest that the borrower repays will go to the supplier. And this is how the supplier is able to earn some interest

on the token that they supply. In the previous video, we saw that for the user to borrow tokens from Rabbit. They'll first need to supply a token and then afterwards they can borrow token. Now the user cannot borrow any amount of token that they wish, there's a limit to the maximum amount that they can borrow and this limit is calculated by what's called loan to value. Loan to value is a protocol settings that is set for each collateral. It determines the maximum borrowing power of a specific collateral. So each collateral will have a different LTB setting. Let's look at an example. Let's say that E as a collateral has a LTB of 75%. So if you deposit one ETH as collateral, then this means that you can borrow any token inside the AI protocol up to 0.75 E

worth of tokens. Let's plug in some numbers. So, let's say that we put in two ETH as collateral when one ETH is equal to 3,000 USD. Now, let's ask the question, how much USD worth of tokens can we borrow from the AB protocol? To calculate the maximum borrow in terms of USD, we'll apply this equation. Take the LTB. Since the collateral is ETH, we'll take the LTB settings for ETH and then the collateral amount and then multiply this by the EU USD price. This will give us the maximum borrowing in terms of USD. ELTB is 75%. So this will be 0.75.

In this example, we deposited two E. So the collateral amount will be 2. And the price of E is $3,000. So we multiply this by 3,000. And this turns out to be $4,500. So for depositing two E when one E is equal to $3,000. Maximum amount of tokens that we can borrow in terms of USD will be $4,500 worth of other tokens. For example, assuming that the stable coin die is $1. Then we will be able to borrow $4,500 D. In the previous video, we saw example of how to calculate the maximum value that a user can borrow from the A protocol. Essentially, this was based on the LTB of the collateral, the amount of collateral that they

deposited, and the price of the collateral. In the example, we calculated that this was $4,500. However, the price of the collateral is always changing. So, let's say that you borrow the maximum amount of USD that is possible, $4,500, and the price of ETH goes down, let's say, to $1,500. So, now this user is under collateralized. the amount of collateral that they deposited is less than the amount of tokens that they borrowed. This condition that the current amount that the user has borrowed is more than the amount of collateral that they deposited is quantified into a single number called health factor. So in this video I'll explain what health factor is. Health factor is a number that determines whether a borrower is over

collateralized or not. When the health factor of a user goes below one then their collateral can be liquidated. Now to calculate the health factor there are two other concepts that we need to cover. Liquidation threshold and average liquidation threshold. Let's start with liquidation threshold. Liquidation threshold is basically just a number between 0 and one with the condition that it is greater than or equal to LTB loan to value. Loan to value is a number that is specific for each collateral. So liquidation threshold is also a number that is specific for each collateral.

Okay. Moving on, we have the average liquidation threshold. The basic idea is that we'll need to calculate the average of all of the liquidation threshold for a user's collateral. So it is a weighted average of all of the liquidation threshold for all of the collaterals that user has deposited. To be more precise, we'll define three terms. We'll define CR of U to be the USD value of collateral locked in a reserve bar by user U. Each token will have a reserve of its own. So you have a die reserve, USDC reserve, ETH reserve and so on. If user U locks one E as collateral into the E reserve and let's say that one E is $3,000, then C R of you for this user for E will be 3,000. This user has

locked one collateral and the USD value of one E is $3,000. How about for D? Let's say that this user has not locked any die as collateral. Then C R of U for this user for the reserve die will be zero since this user has not locked any die as collateral. Okay. And then we have a similar term called B RU. It's basically the same thing except instead of collateral this will be the amount of token that they borrowed from a reserve in terms of USD. For example, let's say that the user has borrowed 3,000 D. Then B R of U for this user where R will be D will be 3,000. Okay. And then we have the last term L of R. This will be the liquidation threshold specific to

reserve R. Now we can come up with the equation for the average liquidation threshold for user U. Let's call this L of U. And basically this will be the weighted average of all of the collaterals that this user has provided multiply by the liquidation threshold. So for each collateral that this user has deposited, we multiply that amount by LR and then sum the total. And then we divide this by the total amount of collateral that this user has locked. This is average liquidation threshold. This number will be used in the next step to calculate the health factor.

Health factor is a number that tells the a protocol whether a user's collateral can be liquidated or not. To be more precise, let's define H of U to be the health factor of user U. The health factor of user U is equal to the average liquidation of the user multiply by the total amount of collateral that this user has locked in the AB protocol in terms of USD then divide by the total amount of tokens that this user has borrowed from the A protocol in terms of USD. The user's collateral can be liquidated if the health factor of the user is less than one. This equation is a little bit unintuitive but once we plug in this equation into this condition and then rearrange it then it will become more clear. So let's start by copying this equation. So this is the

condition for liquidation. Let's replace this HU with this equation. So this is the condition for liquidation. Now let's rearrange this inequality. Bring the total amount that the user has borrowed to this side of the equation and then divide both side of the equation by the total amount of collateral that they have locked. So now the equation will become we can replace this one that the condition for liquidation is that the average liquidation threshold of this user is less than total amount that they borrowed divide by the total amount that they have deposited. And for simplicity let's say that the user only deposited one collateral. In this case the average liquidation threshold of a user will be

equal to the liquidation threshold specific to the collateral that the user has deposited. Since here we're assuming that the user deposited one collateral, we can say that the LTB specific to that collateral is less than or equal to the liquidation threshold of that collateral. Now remember that when a user borrows from the AB protocol, the total amount that they borrowed divide by the total amount that they deposited as collateral must be less than or equal to the LTB loan to value. However, when the user's collateral can be liquidated, we see the inequality flipped. LTB is less than or equal to the amount that they borrowed divide by the amount that they deposited as collateral. So in a healthy condition you have that the LTB

is less than or equal to amount that they borrowed divide by the amount that they deposited. This is the condition for overcolateralized loan. They deposited more collateral than the amount that they borrowed. However, in the case of liquidation, you'll see that this LTB in this simple example of borrowing one collateral, we'll see that this LTB is less than this ratio. So that's the intuition behind how health factor is calculated and how health factor less than one for a user means that this user's collateral can be liquidated. What is leverage? In simple terms, leverage means to buy something with borrowed money. And why would you want to do that? The reason is it can amplify both the profit and the loss.

The way it works is you first borrow money. In the context of DeFi, the token that you borrow can be any type of token. It can be a stable coin or it can be a volatile token. But for simplicity, let's say that we borrow some stable coin. And here I'll denote stable coin as USD. So we borrow USD. That is the first step. The next step is to buy ETH. When you buy ETH, you're expecting that in the future the price of ETH will appreciate. It will increase. If your prediction is right, then you will sell the ETH when the price goes up and then repay the USD, the amount of stable coin that you borrowed. This is how leverage can amplify the profit. Let's look at an example. The first step is to borrow

stable coin. We'll imagine that we are interacting with D5 protocols. And we also assume that the only loan that we can get is a over collateralized loan. In the case of AB, the amount of stable coin that we can borrow will be limited by the LTB and the amount of collateral that we deposit. So let's say that the LTB of ETH is 80% and the amount of collateral that we deposit is 2 E. We also say that the current price of ETH is one E equal to $3,000. Okay, so first let's calculate the maximum amount that we can borrow from AI. This is LTB multiplied by collateral amount and then multiply by the collateral price. Plug in the numbers and we get 0.80 for LTB 80%, two for collateral amount and the

US price of E is 3,000. This is equal to 4,800 USD. So this is the maximum amount of USD that we can borrow from a over collateralized lending protocol like AB. The next step is to buy ETH with the borrowed money. We saw that the maximum amount of USD that we can borrow is 4,800 USD. So let's say that we borrow 4,200 USD and then swap this 4,200 USD to ETH. The current price of one ETH is 3,000 USD. So if we have 4,200 USD, then we'll be able to buy 1.4 E. Next step is to sell E that we bought if the price of E goes up. So let's say that the price of E went up from 3,000 to 4,000 USD.

Let's swap the ETH that we bought back to USD. We have 1.4 E and the current price of one E is 4,000 USD. So, we get back 5,600 USD. The last step is to repay the USD that we borrowed. For simplicity, we'll say that the interest on borrow is equal to zero. We borrow 4,200 USD. So, this is the exact amount that we need to pay. Let's now calculate the profit. When we sold our EE, we got back 5,600 USD. The amount that we have to repay is 4,200 USD. The leftover is 1,400 USD, which is equal to our profit.

Finally, let's compare the profit between taking a leverage and not taking a leverage. So, taking a leverage, the profit was 1,400 USD. Now, remember that at this point, we still have our two E collateral. If you were to not take a leverage, let's see how much profit we would have made. Let's say that we don't take a leverage, so we don't put this as collateral. We start out with one E equal to 3,000 USD. Later on, the price of E goes up to one E is equal to 4,000 USD. If you have bought those two E when one E was equal to 3,000 USD and then sold it when one E was equal to 4,000 USD, the profit will be 2,000 USD. So if you did not take a leverage and we bought two ETH when one ETH was equal to 3,000 USD and the price of ETH went up

to 4,000 and we sold our two E here, the profit will be 2,000 USD. Finally, let's compare this with the profit that we would have made if we took out a leverage. If we took out a leverage, we got back 1,400 USD. And remember, at this point, we still have the two E. If we had bought two ETH when one E was equal to 3,000 and then we sold it when one E was equal to 4,000, that's an additional 2,000 USD. So the difference in profit between taking a leverage and not taking a leverage and also selling our ETH is 1,400 USD. By taking a leverage, we made more profit. However, if the price of E went down instead of going up, then we would have made more loss compared to not taking a leverage.

So by taking a leverage you take on more risks and there's a possibility of making more profit and also more loss. We saw a simple example of creating a leveraged position in the previous video. What we did was we deposited collateral and then borrow some money and then bought more collateral. Okay, but are you just going to hold on to this collateral? Are you going to just let it sit waiting for the price to go up until you can close this position? Well, here's an idea. How about if you take this collateral and then repeat the process? deposit collateral, borrow, and then buy collateral again. Now we have a collateral again. So why not repeat this process again? So it looks like we can repeat this process and definitely to create a infinite leverage. However, for

over collateralized loan, you'll see that there's a limit to the leverage that we can create. So in this video, I'll explain why max leverage is given by this equation where this L is equal to the LTB. To derive the final equation of max leverage, we'll start with some definitions. Let's say that C is equal to the initial amount of collateral that was deposited and P will be the current price of the collateral and L will be equal to the loan to value LTB. The process of creating a leverage position was to first borrow some amount of USD. The maximum amount that can be borrowed is the loan to value times the amount of collateral times the price of the collateral. The next step is to buy more collateral. The amount of collateral

that can be bought is the amount of USD that we borrowed divide by the price of the collateral. And this simplifies to L * C. LTB multiplied by the amount of collateral. And then the next step to close the loop is to deposit this L * C amount of collateral. Again, let's summarize these three steps. We first started with C amount of collateral. This is our initial amount of collateral that we deposited. And when we did that, we were able to buy L* C amount of collateral. And here we're assuming that there's no trading fee. Now let's see what happens if we repeat this cycle many times. What is the limit as we repeat these three steps over and over again? Let's calculate the maximum

amount of collateral that we can collect for a leveraged position. Initially, we start with C. This is the amount of collateral that we have. We borrow some stable coin and the maximum amount of collateral that we get back let's say is L * C and now we're going to deposit this collateral again. We started with L * C and to this we multiply by L. So we get L² * C and then we do again we start with L² * C borrow this much amount of USD and then swap it back to collateral and we'll get back this much amount of collateral. Okay. And we can continue this process indefinitely. Since there's a C in every term, we can also simplify the equation. Now, this part of the

equation inside the pink rectangle is a well-known equation called a geometric series. There's an explicit formula for calculating the sum of all of these terms, which is given by this expression. And for L strictly less than one, this converges to a number 1 / 1 - L. Using this fact when we apply it to this part of the equation we get that this equation is less than C * 1 / 1 - L and this tells us that the maximum leverage the maximum amount of collateral that we can collect for a leveraged position is C * this factor 1 / 1us L. Let's go through an example

with some numbers. Let's say that the LTB is equal to 0.8 8 and let's calculate the maximum leverage. This is given by 1 / 1 - L. Plug in the numbers and this is equal to 1 / 1 - 0.8 which is equal to 5. This tells us that the maximum leveraged position that we can create for overcolateralized loan is 5 * the amount of collateral that we initially deposit. So far we saw how to create a increased leverage position by looping. We loop through the process of depositing collateral, borrowing some stable coin, and then buying more collateral. And then we repeated that process over and over again. However, if you were to do that with smart contracts, then it would use up a lot of

gas. We can create the same result using a flash loan. And here we don't have to loop through the three steps. So it will save some gas. To open a leveraged position, we will start with some initial amount of collateral. The next step is to flash loan USD stable coin. Then using that stable coin that we just flash loan, we'll buy more collateral. The next step is to deposit the collateral. The collateral that we had from step zero and the collateral that we just bought. Supply both of them to AB as collateral. Once the collateral is deposited, we can borrow stable coins from the AB protocol. The stable coin that we just borrowed will be used to repay the flash loan from step one. And this is how you create a large leveraged

position without looping through the process of depositing collateral, borrowing stable coin, and then swapping the stable coin for collateral and then redepositing it as collateral. Let's see how to close a leveraged position using flash loans. Before we start, remember that this user has borrowed USD and has collaterals locked in a bit. So to close a position, this user will first get a flash loan of a stable coin and then use this stable coin to repay the stable coin that this user borrowed. Once the stable coin debt is repaid, this user can now unlock the collaterals that he deposited. This collateral will include the collateral that the user bought and the initial amount of collateral that the user deposited. sell this collateral

on a decentralized exchange such as unis swap and then repay the flash loan. Whatever amount that is left over from swapping the collateral to stable coin and then repaying the flash loan is the profit that the user will receive. And the user can also unlock the initial amount of collateral that he locked. Given that we provide some amount of collateral, what is the maximum amount that we can borrow from a flash and then create a leveraged position? Surprisingly, the answer turns out to be a simple equation. To derive that equation, we'll start with some definition. Let's say that B is equal to the total borrowed USD and C will be the total collateral in USD. C0 will be the initial amount of collateral in USD deposited by the user and L will be the

loan to value ratio for that collateral. Since the amount that we can borrow must be less than the amount of collateral that we deposit, here we have our first equation. The total borrowed divide by the total collateral must be less than or equal to the loan to value LTB. Next, let's introduce a variable called F. We'll denote this as the flash loan amount in USD. The amount that we're going to borrow using flash loan. And then we have our second equation. The total borrowed will be exactly equal to the total amount of flash loan. In other words, we're going to borrow this much amount to repay the flash loan. Moving on, we'll say that C of S is the USD amount of collateral swapped from a

flash node. And here we will assume that there's zero slippage on the trade and also the swap fee is equal to zero. So although the amount that we borrow from a flash node can be converted into the collateral. Next, we'll rewrite this C of S the USD amount of collateral that we just swapped using the flash loan. We'll write this as some multiple of the initial amount of collateral that we deposited. C 0 is the initial amount of collateral that we deposited in terms of USD and K will be some number. When we multiply K with C0, we get CS. Now that we have equation for CS in terms of C 0, let's now rewrite C. Again, C is the total collateral in USD. And this is

equal to C 0, the initial amount of collateral that was locked plus the amount of collateral that was swapped. So, I'll copy this and then say C0 is equal to the initial amount of collateral that we locked plus the amount that was just swapped from the borrowed stable coin. Okay? And this is equal to next we're going to use this part of the equation to replace CS. So, this is equal to CS is equal to CS is equal to some multiple of C 0 K + C 0. And we can further simplify this equation. This will be equal to 1 + this value K time C 0. We'll come back to this equation later. So I'll just

highlight it for now. So now let's put everything together to solve for F. Remember F was the flash loan amount in USD. Let's start with these two equations that the amount to borrow must be less than the LTB and the amount of flash loan will be the amount to borrow. I'll paste these two here. Okay. So let's rewrite this equation as let's just replace the B with a F. So replace the B with the F. Then we get this equation. Next let's replace the C with the equation that we derived. So this is equal to 1 + K * C 0. And next let's replace F. Earlier we said that the amount of collateral that we're going to

get will be all of the amount that we flashed. So let's use this equation to replace F. F is equal to CS the amount of collateral that was swapped. Okay. But we also know that CS is equal to some multiple of C 0 the initial amount of collateral. Okay. So let's replace this CS. This will be equal to replace the CS with K * C 0. And now notice that on top we have C 0 and on the bottom we have C 0 as well. So these two cancel out. Okay. From this equation, we'll finally put it together by applying this equation. Remember we started out with B / C and this must be less than or equal to the LTBL. So the equation that we

derived must also be less than equal to L. Okay. So now we can solve for K. So take this equation and then simplify the terms. So we have this equation and we're going to solve for K. Let's bring this 1 + K over to the right side of the inequality. The right side of the inequality will be L + L * K. And now let's bring over this L * K over to the left side of the equation. And then this plus will become a minus. Now we can simplify this term. This term over here we can pull out the K and it becomes K * 1 - L. And finally we divide both side of the equation by 1 - L. So this will come to the right side of the equation

and we get that k must be less than or equal to the ltbl / 1 - l. Once we have a upper bound for this value k, we can now solve for f. So going back up, I'm going to copy and paste some equations. We're going to need these two equation. This one over here to solve for f. So f is equal to c. Yes, the amount of collateral that was swapped. And we also know that this is equal to some multiple of the initial amount of collateral that was deposited. And we also have a upper bound for the value K. K must be less than or equal to the LTBL divided by 1 minus L. That's K. We multiply this by C 0. Now we have the expression for the amount of flash loan that we can borrow.

The maximum amount that we can flash loan must be less than or equal to L / 1 minus L multiplied by the initial amount of collateral in terms of USD that we deposited. This is the maximum amount that we can flash on. And if we were to take out this maximum amount, this will give us the maximum leverage that we can take when the LTB is equal to this value. Here's the contract that we're going to be building and why we're going to be building it like this. First, it has a proxy contract where only the owner of this contract will be able to call a function called execute. When this owner calls the function execute, it will delegate call to another contract called flashb. And this flash contract will call into the a getting

flash loans, supplying collaterals, borrowing tokens, repaying the borrow tokens, and withdrawing the collaterals. To create a leverage position using flash loans, the owner will first call the function execute which will delegate call to the flash contract. The flash contract will call flash zone and then the a protocol will call function called execute operation. This call will be forwarded over to the proxy contract. From the fallback of the proxy contract, it would delegate call back into the flash contract which will contain the logic for how to create a leverage position using flash loan and also how to close a leverage position using a flash loan. Now the reason why the contracts are designed like this is so that the positions can be managed easily

and to save gas. Remember that when a user or a contract borrows from the a there is a specific health factor that is associated with that contract or the user that borrow tokens if he had a single token that allowed many users to borrow tokens from a then the health factor will be associated with the contract and not the user. So for example one user might supply some token and then another user might borrow tokens on the first user's behalf. Basically the second user is getting a free loan from the collateral that the first user deposited. So to avoid this every user will have a proxy contract where only that user will be able to call functions on the proxy contract.

Basically this will isolate the health factor for every user. Okay. And the other reason why the contracts are split between proxy and flash is because the logic contained in flash can be reused by any proxy contract. So imagine that there are multiple proxy contract. All of them can do a delegate call to execute the logic inside flash to get a flash loan and create or close a leverage position. So this is how the contract that we're going to be building is designed and the reason why it is designed like this. Let's go over the solution for how to get the max flash loan amount in USD. The values that we'll have to return are the maximum flash loan amount in USD with 18 decimals. the price of the collateral

asset with eight decimals, the LTB with four decimals, and the max leverage also with four decimals. Okay, so the first thing that I'm going to do is get the LTB and the price of the collateral using the contracts from AB. The contracts of AB are initialized inside a contract called AB helper inside a folder source A. So I'll click on this file called AB helper and the contracts that we're interested are called data provider and Oracle. The data provider is an interface called IO data provider and the Oracle is I aracle. So let's take a look at these two interfaces.

Going to interfaces then clicking on NB I'll open I A Oracle and I pull data provider. Let's start with I data provider. There is a single function called get reserve configuration data. Takes in the address of the token and it returns a bunch of data. But the data that we're going to need for this exercise is the decimals the decimals of the token and the LTB the LTB of the token. Let's copy this function signature and then paste it inside here. So we'll come back to this later. Okay.

And then let's also do the same for the I oracle. The function get asset price will return the USD price of a token with eight decimals. So let's also copy this and then go back here and then I'll also paste this here and also go back and then copy this comment saying how many decimals the price returns. Okay, so let's start by getting the decimals of the token and the LTB setting. We know we need to call this function get reserve configuration data. What contract do we need to call? Going back to the a helper, we can see that the contract that we need to call is a data provider. This is a contract with the interface for ipole data provider. Okay.

So going back here, we'll say data provider dot get reserve configuration data. And inside here, the asset will be the collateral. The address of the collateral is provided as input. Here I'll type collateral. Okay. And then when we call this, it's going to return a bunch of data. Let's take this and then put it here and then say data provider get reserve and then assign the return value to all of these variables. We're not going to need all of them. So let's remove them. Okay, so I removed some of the variables that we're not going to need for this exercise. Now notice we accomplished one of the tasks.

One of the task is to return the LTB. And here we already got the LTB from calling the function get reserve configuration data. Let's directly assign this LTB variable to this output. We can do this by simply removing this. The variable is declared here. So we simply just assign it. And to get the decimals, what we'll need to do here say in 256 decimals. First declare it and then inside here we'll assign it. So we got the LTB and the decimals. Let's move on.

Next let's get the price of the collateral. So the function that we need to call is get asset price and the contract that we'll need to call going back to the other helper we can see that we need to call the oracle contract. So here we'll say oracle.get asset price and the asset will be the collateral and it's going to return a single value in 256 the price of the collateral with eight decimals. So let's assign this to a variable called in 256 price. Price is equal to oracle get asset price. Okay.

And now notice we've already declared this variable called price as a output. So we can omit this declaration and then simply assign the price to the variable that is going to be returned. The price of the asset has eight decimals. One of the task is to return the price of the collateral with eight decimals. So we also accomplished this task. Okay, moving on. Next, let's tackle the easier task of getting the maximum flash amount and the max leverage. We already know how to calculate this max leverage. The max leverage is given by LTB / 1 minus LTB. I'll copy this and then paste it here and say max lab is equal to the LTB / 1 1 - LTB. Now LTB has let's see it

has four decimals. So if you have four decimals 1 E4 which is equal to 1 followed by four zeros then this is equal to 1. So in our case we have one over here. We need to make this to have four zeros. Can do this by saying 1 E4. And also if LTB is smaller than this number 1 E4 minus LTB then the division will round down to zero. We don't want this to happen. So we'll first multiply this LTB by 1 E4. That completes the calculation for max leverage. Let's tackle the final task of calculating max. Max is the maximum flash loan amount in USD with 18 decimals. And how

do we calculate this? Let's go back up. Here we have the equation flash loan USD. Maximum flash loan USD is given by this equation. So let's say max is equal to base collateral in USD. To get the base collateral in USD, we'll need to multiply the collateral base collateral amount by the price that we fetched from the oracle. say base call amount and then we multiply this by the price. Now the price has eight decimals. So to remove the eight decimals here we'll at the end we'll divide by 188. Also we'll need to return this max value with 18 decimals. We don't know how many decimals the token has. So let's

normalize this token amount to have 18 decimals. We can do this by saying 10 * 18 minus decimals where decimals we fetched it when we call the function get reserve configuration data. Okay. So now this value will represent the base collateral in USD with 18 decimals. The next step is to multiply by this expression LTB / 1 minus LTB. We already sort of seen how to calculate this max leverage. The code is over here. So I'll copy this and then paste it here. So we have the base collateral amount with 18 decimals multiply by priceide by 188.

Since the price has 8 decimals, then we multiply by LTB / 1 minus LTB. Since this value already has 18 decimals, we don't need to multiply this part by 1. So let's remove this 1. Okay. And this is how you will calculate the maximum flash loan in USD. Okay. Let's execute the test for this exercise. Inside the terminal, I'm going to execute forge test fork URL. The test file that we're going to execute is called exercise a flash. And the test function that we're going to execute is called test get max flash stone amount USD. Okay. And our test passed. And we can see here that LTB for our ETH is 75% and the max leverage is three. You can also see the

collateral price which is around $4,142 and the maximum flash loan amount in USD which is roughly $12,427. The next part of creating a contract that does flash leverage is to complete the function open. This function will use flash loan to create a leveraged position. Okay, the first thing that we'll have to do is pull in the collateral from message sender ERC20. And what is the address of the collateral that we need to pull in? Scrolling back up, let's look at the parameter for open params. Scrolling up, you see open params. The address of the collateral is specified in the input collateral. Here I'll type params

collateral dot transfer from message sender to this contract. For the amount, how much do we need to pull in? Well, how much did the user specify? The amount that the user specified is stored inside coal amount params. Coal amount. Okay. So that's transferring the collateral from message sender into this contract. The next step is to initiate a flash loan. And to do that there's a helper function inside the contract of a helper. Okay, here it is flash loan.

It's going to take in three inputs. Token, amount, and some data. Okay, going back here, we'll call flash loan. Okay, and what is the coin that we need to flash loan? What is the token that we need to flash loan? Is it the collateral or is it the stable coin? Well, let's scroll back up to review what the flow is for opening a leveraged position. Okay, so here it is. I'll copy this comment. Steps to open a position. Then go back down and let's paste this here. Steps to open a position. Flash zone stable coin. So the token that we'll need to flash stone is the stable coin.

Inside the input open params where is this address of the stable coin stored. The stable coin is stored under the address coin. But here we'll say params.coin. Next is the amount amount. The amount of stable coin that we want to flash. Where is this stored? It's stored as coin amount params.coin coin amount. Okay. And then data. What data do we need to encode? The data that we'll need to encode is the flash loan data. So let's copy this so that we know what parameters to pass. And then we'll need to encode it as byte. So say abi.incode. And then we'll initialize

our strct inside here. Flash loan data. Okay. Let's start with coin. The address of the coin will be pram.coin. Address of the collateral will be params. And open is a boolean. Is this a flash stone to open a leveraged position? Yes, it is. So, we'll set this to true. Address of the caller. Caller here will be message. The address that call the function open to initiate a leveraged position. Message sender. Coal amount. What is the amount of collateral that we're going to initially deposit?

This is stored in as prams.co amount. prams.core amount. Okay. And then swap prams. This swap pram is a data that will be forwarded over to a swap helper contract which will call into a dex to execute the swap. And this data is stored inside our inputs open params. So we can just simply forward this say params. swap. Okay. So that will initiate a flash node. Later we'll need to implement the call back of the flashnome. But for now let's complete this function open. The last part is to check the help factor after we do a flash node to create a leveraged position. We want to make sure that the help factor is greater than some number

that the user specifies. Okay. So how do we get the help factor? Well, let's go to the a helper contract and look for a function where we might be able to get the help factor. And here's a function called get health factor. It takes in single input address that we want to get the health factor for and it returns the health factor of the user. So let's copy this function and then paste it over here. Get health factor of this contract address this. And we want to check require that this is greater than or equal to the health factor that the user specifies. The health factor that the user specify is stored inside open params min health factor

params min health factor. Let's say with the error message health factor is less than min. Okay. So that completes the open function. Next let's implement the flash call back when we're opening a leveraged position. So we'll write our code inside this internal function called flash long call back. And just to explain what's going on here, when we do a flash loan, this function is stored inside the AB helper. So here it is. It will execute a flash loan on a contract. The A contract will call back into a function called execute operation. And here it does some authorization check and then call internal function called flash loan callback. The flash loan call

back is to be implemented by the contract that inherits this AB helper. In our flash lab contract, this contract inherits the a helper. And inside here, we'll need to implement the flash known callback. So let's implement the logic for opening a leveraged position. And to do that, I'm going to first go up and then copy this steps again so that we know what code we need to implement. Okay, so here it is. So we did a flash loan of stable coin. The next step is to swap stable coin to collateral. Supply the swap collateral and then borrow stable coin. then repay the flash note.

The simplest step is repaying the flash note. So let's start with that. Let's first compute the amount that we need to pay. UN 256 repay amount is equal to will be equal to the amount that we borrow plus the fee that we'll have to repay. Let's also initialize the address of the stable coin and the address of the collateral as IC20. And to do that, we'll first need to decode this bytes params into the flash stone data. the flash loan data, the one that we ABI encoded into bytes over here. We're now going to decode this. Going back down here, we'll say flash loan data memory.

We'll name this data is equal to AI dot decode the raw bytes params as flash loan data. Okay, once we have the data decoded, we can get the address for the coin and the address of the collateral. So let's initialize them as IRC20 interface. IRC20 let's call this coin is equal to IRC20 data coin. Then we'll do the same for collateral. IRC20 collateral is data. Initialized as IRC20. Okay. So we can now finally complete the last step repaying flash loan since we initialized the coin and collateral as a interface.

So the last step is to approve AB for the amount repay amount. This is the amount that we must repay. So we say coin dot approve and then say address and what address we need to pass in here. Let's go to the a helper and then look for the address of the a contract. The a contract is called pool. So here we'll pass in pool. For the amount rep we pay amount. Okay. So that's step four. Next let's move on to step two. swap stable coin to collateral. So to do this, we'll call another helper contract. The helper contract is located under a and it's called the swap helper contract. The flash lab contract inherits the swap helper contract. So

all of these internal functions that are declared here are available inside our flash contract. And the function that we'll need to call is called swap. This contract will swap a stable coin into RE or RE into a stable coin depending on whether we're creating a leveraged position or closing it. If you're curious, you can check out the internals for how swap between unis swap B3 and swap between balancers are implemented. Without going into the details here, I want to focus on how to create a leveraged position or close a leveraged position using a flash note. So we'll treat this function swap like a magical function where if we pass in the inputs we'll get what we want. The inputs that we need to pass in are token in token

out amount in and amount out min and any data that is specific to the underlying dex that is swapping the tokens and it's going to return a single output amount out. And that's all you need to know about how to call this function. Pass in the correct parameters and we'll get amount out. Now, if you want to create a flash leverage contract for other tokens, then you'll need to modify this internal logic. You might only need to swap tokens using unis swap b3 or you might need to swap tokens involving other AMMs such as balancer and curb. Let's copy this function signature so that we know what inputs to pass and what output will come out. And then let's go back to our flash leverage contract. So, we're working on step two,

swap stable coin to collateral. And the function that we'll call is a internal function called swap. It's going to return amount out. U in 256 amount out. And these are the parameters that we going to pass in. Token in will be we're swapping from stable coin to collateral. So token in will be the address of the stable coin. Address of the coin. Token out will be the address of the collateral. Address collateral. amount in amount in will be the amount that we flashed on amount and amount out min.

Where can we get this value from? Let's scroll back up and inside the strct called open params. This is the input that we pass in when we call the function open. It has a pram called swap. Let's take a look at this strct. So inside here it has two inputs. some arbitrary data that is passed to the underlying AMM and also a field called amount out min. So let's use this here. This will be data dot swap dotamount outmin and the arbitrary data to pass to the underlying amm. This will be data swap data. Okay. So this is how we will swap from stable coin to collateral. And

to be more precise, let's rename this variable amount out to collateral amount out. Co amount out. Okay, so that's step two. The next step is to supply the swapped collateral and the base collateral. To supply the collateral to AB, we'll call the internal function called supply. Takes in two inputs. The token to supply and the amount to supply. Let's first calculate the total amount of collateral that we're going to supply. Let's say UN 256. whole amount is equal to this is equal to the amount of collateral that the user specified to initially deposit. This is stored inside a field called co amount inside the strct/ loan data. So this will be data

dot coal amount plus the amount that was just swapped call amount out. We'll need to approve a to spend this amount of collateral. So say collateral dot approve address of the pool address of the a protocol for the amount core amount and then we'll call the internal function supply address of the collateral for the amount core amount. Okay, the next step is to borrow stable coin for the amount flash amount plus v. Again we'll use the function that is declared inside the other helper contract. The function that we'll call is called borrow. takes in two inputs, token and amount. So say borrow. The token that we're going to

borrow is the address of the coin. Address of the coin. Amount that we're going to borrow is the amount that we're going to repay to the flash loan. Repay amount. Okay. And that completes step four. So let's just review what we did so far. Inside this flash loan call back, we first bought collaterals with the stable coin that we flash loaned. Next, we took this collateral that we just bought and then also added the collateral that the user initially deposited and then supplied it as collateral to ABT. Once we have collateral locked inside a we can borrow tokens. So, we borrow a stable coin and the amount that we borrowed will be the amount that we repay to the flash loan.

And then we approve the AB contract for the amount that we're going to repay. And that completes the flash loan call back for opening a leveraged position. Let's make sure that the code compiles. Forge build. Okay. And our contract compiles once we open the leverage position. And let's say that the price of beef went up significantly. Now is the time to close our position and realize our profit. The first step to closing our position is calculating the current debt that we owe to the AB protocol. To do this, there's a helper function inside the AB helper contract. The function is called get debt. Takes in two inputs. The user and the token.

the token that was borrowed. And remember after we took out the flash loan, we deposited collateral and then borrow the stable coin to repay the flash loan. So our debt will be in stable coin. Let's say unit 256 coin amount is equal to the function call the function get debt for this contract address this. And how do we get the address of the stable coin? Well, let's scroll up inside the str close params. We can see the address of the coin is stored inside coin paramscoin. Okay, so this is how you get the current debt that we owe to the a protocol. We'll need to repay all of this to be able to close our position

and then withdraw our collateral. And the next step is to initiate the flash loan by calling the helper function called flash loan. Let's copy this code that we implemented when we open the flash loan and then paste it here. Okay. And then we'll modify this. And also let's go back up to see the steps that are involved in closing a leveraged position and then I'll paste it here. So we'll need to flash zone stable coin. So the token will be coin. The amount will be the current debt that we owe to the a protocol. Coin amount. Okay. And how about flash loan data coin collateral are the same. Open this will be for closing a position. So this will be

false. Caller will be message sender. Coal amount. What does coal amount mean in this case for closing? Coal amount mean this is the amount of collateral to keep. So this is the amount of collateral that is not to be swapped. Okay. And it's specified inside the strct close params. So this call amount we'll keep it the same and the swap params will also be the same. Okay. So that completes the function close. Next, let's implement the flashal call back. when we're closing a position going all the way down we're going to complete the internal function flash zone callback and before we do that I want to copy this comment on how to close a flash zone and then we'll paste it here previously we worked on the logic for

opening a position but now there are two cases opening a position and closing a position the flash call back will be called for both opening a position and closing a position and the logic will be different This part will be for opening a position and whatever code that we write here will be for closing a position. So let's create the conditional statement if data.open then execute the logic for opening a leveraged position. Otherwise we are closing a position. So let's execute the code for closing a position. In both cases we'll need to repay the flash loan. So this part of the logic will remain the same. We've

done the first step flash known stable coin. The next step is to repay stable coin debt. And to repay we'll go to the other helper contract and look for a function called repay. This function will repay the tokens that we borrowed. Takes in two inputs token and amount. And then it's going to return the amount that we repay. Okay. So going back the first step is to repay repay coin. So address coin further amount amount. This is the amount that was flash loan which is also equal to the current debt that we owe to the abit protocol and we calculated this amount inside the function close. Okay. But before we repay we first have to approve the a protocol to be able to spend the token

from this contract. We'll say coin.approve address pool for the amount amount. Once we repay we can now withdraw our collateral. Again we'll call the function inside the a helper contract called withdraw. This will withdraw the collaterals. Say withdraw withdraw the collateral. Now the collateral that we deposited will be earning some interest. And to withdraw all of the collateral here specify type 256.max. This will tell the abit protocol to withdraw all of our collateral including the interest that we earn for depositing this collateral.

The actual amount that was withdrawn is returned. So let's assign this to a variable unit 256. Let's call this collateral withdrawn. Coal with John. Okay. The next step is to swap the collateral to the stable coin. But before we do that, let's transfer the collateral back to the caller. Say collateral dot transfer to data.aller for the amount amount that the caller specified to keep. Data dot call amount. Next, let's swap the collateral to the stable coin. The amount to swap, let's call this unit 256 call amount in is equal to the amount that was withdrawn minus the amount that was sent to the user. Call withdrawn

minus data call amount and then we'll call the internal function to swap. So I'll copy this code and then paste it here. The token in will be collateral. Token out will be coin. Amount in will be coal amount in and amount out min will come from swap data and the arbitrary data for swap will also come from swap that data. Since we're swapping collateral to coin, this will be coin amount out. Okay, what is the next step? So we swap collateral to stable coin. Now we need to repay the flash loan. But before we do that, if there's any profit, let's transfer the profit over to the caller. Otherwise, if there's a loss, let's also ask the

caller to repay for the loss. So, let's say if coin amount coin amount out is less than repay amount, then there is a loss. So, we'll ask the caller to repay to cover for the loss. coin dot transfer from data.aller caller to this contract for the amount the difference repay amount minus coin amount out otherwise if there's a profit and then we also send the profit to the caller coin dot transfer transfer to data dot caller for the amount in this case coin amount out will be greater than or equal to repay amount coin amount out minus repay

amount okay and that completes the exercise for close. Let's try executing the test. The command to execute is forge test fork URL. The file to test is called exercise a flash li and the function that we'll call is called test flash. This function will both test opening a leveraged position and then immediately closing it. So we expect to make some loss. Okay. And our test passed. When we open the position, you can see that the health factor reached close to one 1.05. So that's really close to getting liquidated. And then after we closed the position, we made a loss of roughly $94. However, we got our one collateral back. Balancer B2 is a

AMM that allows you to stake the liquidity and earn rewards. The mechanics for earning the reward is based on a design invented by Curb Finance. This mechanic is called voting escrow tokconomics, also known as VE tokconomics. The way it works can be a little bit confusing. So in this video I'll explain how balancer v2 contracts are designed, how it works, and how the voting escrow tokconomics works with balancer v2. So let's say that we have a user. This user is going to be a liquidity provider to the balancer B2 AMM. The way the balancer B2 contracts are designed is that a single contract called a vault contract will hold all of the tokens. So if you have a AMM of D and E instead of having a separate

contract for these two tokens all of the tokens although the die and although the E will be in this contract and the same goes for let's say we have the rocket pool our E token and we want to pair it with E. Again these two tokens are inside the vault contract. Now different token pairs might require different logic for the AMM. For example, for the D and W token pairs, we might want to have a pool that is like the constant product AMM. And for tokens like D, USDC, and USDT, we want to pull like curve V1's stable swap contract. So the logic of the AMM, depending on the tokens, will live outside of this bolt contract. There are four different types of pool that contain the logic for the

AMM. Weighted pool, this is like the constant product AMM. And then we have the stable pool which is like the curb B1's stable swap contract. And then the meta stable pool which is also like the curb B1's stable swap. And then there's also a custom pool. To add liquidity for example our E and if the user will call the vault contract the token pairs R E and E are registered as a meta stable pool. So the vault contract will execute the logic inside a meta stable pool contract. The tokens will be kept inside the vault contract and the specific logic for the AMM will be executed over here and afterwards the user will receive a LP token liquidity provider token. In balancer this is also called BPT. BPT standing for balancer pool

token. Once the user has some liquidity provider shares in the balancer AMM, this user can decide to stake this liquidity provider shares BPT into a contract called a liquidity gauge. There are separate liquidity gauge for each pool. So for the pool with our E and E if there will be a liquidity gauge contract and let's say that there's another contract with the die E if pair then there will also be a liquidity gauge contract for the die E if pair. So taking this BPT the user can decide to stake his BPT into this liquidity gauge contract. Now why would the user want to stake his BPT into a liquidity gauge contract? The reason is to earn some rewards. The rewards will be the

balancer governance token BA bow. The amount of bow that the user will receive will depend on the amount of BPT that the user stake. So when a user claims the balancer rewards, the balancer mentor contract will checkpoint to see what the balance of this user is inside the liquidity gauge contract. So so far it's a simple contract. The liquidity provider can add liquidity, get some liquidity provider shares, BPT, and then stake it into the liquidity gauge to earn some rewards. There are two things that this user can do with the bow token. He can sell it on a AMM to make a instant profit or he can lock it into the voting escro contract. And by doing so, it will boost the amount of bow

rewards that this user can receive. To lock bal into the voting escro contract, the user will first have to add liquidity to the balancer W pool. Receive the BPT token of balancer W pool and then lock that BPT into the voting escore contract. So the first step is to add liquidity to the pool balancer W. The tokens B and W will be locked inside the vault contract. The logic to be executed will be executed against the weighted pool of balancer W. The user will receive the BPT for bow pool. The user can take this BPT and then lock it inside the voting escro contract. Locking BPT for the bow pool into the voting escro contract will give

this user voting power. This is called BE val. This B val will linearly decrease over time. When the user locks the BPT token, their BE val will be at maximum. And if they don't do anything over time, their B val will decrease. In other words, their voting power will decrease over time. Now, when a user locks BPT into the voting escro contracts, they have several options for how long they want to lock their BPT. Essentially, the longer that they lock their BPT, the more voting power that they will receive. This VBO has several benefits. One of them is that it will give a boost to the balancer rewards.

The way it works is that when the liquidity gauge calculates the balance of this user by locking this BPT into the voting escro contract, it will give a boost to the balance that is calculated inside here. Which essentially means that when the user claims this bell token, they will receive more since they received the boost. Another benefit of locking into voting escore contract is that now this user can vote for the distribution of the bell rewards. And the user can now vote for which pool should receive the bell token and how much it should receive. And the last benefit of locking BPT into the voting escore contract is that this user will now earn some protocol rewards. Part of the protocol revenue that is collected from swaps can

now be claimed by this user. And finally, the way that the user can vote for balancer rewards emission is by engaging with the contract gauge controller. They'll be using their voting power be to vote for which pool will receive the bell rewards token and how much percentage should go to each pool. In the previous video, we saw that a liquidity provider to the balancer B2 AMM can take their BPT token and then stick it into the liquidity gauge to earn some rewards. And if they want a higher reward, they'll need to pair this balancer token with the ETH to get a liquidity provider token for the bow pool and then lock this BPT into the voting escro contract. If this liquidity provider does not lock BPT for bow pool,

then he does not earn a boost on the liquidity token that he staked. The Ora finance protocol streamlines this process of locking this BPT into the voting escro contract and it also allows a liquidity provider to earn a boosted reward of the bell token without locking tokens into the voting escro contract. The way it works is that instead of having the liquidity provider directly engage with the balancer B2 contracts, instead of staking his liquidity provider token into the liquidity gauge, this liquidity provider will interact with the oral contracts. He'll take his BPT, for example, the BPT of our ETH and EF, and then interact with the Our contract. Stake his BPT into the oral contract. The oral contract will

automate the process of claiming the rewards, converting that balancer rewards into balancer WE liquidity provider token, BPT, and then locking it into the voting escro contract. So, in this case, the liquidity provider does not have to go through the step of locking tokens into the boating escro contract. Now since our contract is boat locking this liquidity provider even though he did not boat lock any tokens he'll receive the boost of the rewards since our contract locks balancer rewards into the voting escro contract.

This reward that goes to the R contract is split between the protocol and the users and the user will also receive another reward token that is issued by the Oro protocol the Oro token. Let's look at an example of providing liquidity to balancer V2. The first step is to click on pools. In this example, we'll provide liquidity to the re pool pool. Once you're on the pool page, scroll down and let's look for the re pool. Okay, I see it here. Click on it and then you can add liquidity by clicking on add liquidity and then putting in the amount of R E and E or W that you want to provide as liquidity.

Balancer allows you to single side liquidity, which means that you don't have to provide both the tokens. If you wish, you can choose to provide just one of them. I've already added liquidity. So, scrolling down, here's the liquidity that I provided to this pool. Remember that once you provide liquidity, you get a BPT token. And you can use this BPT token to stake into the liquidity gauge. You can do this by clicking on stake. I've already done it, so I cannot press it here. Clicking on the stake tab, you can see that I have my BPT token staked into the liquidity gauge. Once you have BPT staked into the liquidity gauge, over time you'll earn some BALO token rewards. Once you have BAO, you can claim the BAO reward and then pair it

with a W to add liquidity to the BA W pool. Then you will take that LP token and then lock it into the boating escro contract. To claim the bow reward, click on the BE bow tab. This will take you to another page. And once you're there, click on the claim tab. Scrolling down here, you can see that I can claim some bow as rewards. Click on this to claim some bow tokens as reward. And once you have this, you can add this as liquidity to the bow pool. Then lock the BPT into the voting desk contract. Going back to the balancer pool page, scroll down and then find a pool called Bow W. Click on this and then add your liquidity by clicking on add liquidity. Again, you can either single side liquidity or add

both tokens as liquidity. Once you do that, we'll again go back to the page of be bow. I've already locked some on BPT for the bow web p. And you can see here that my be bow is 0.350 and over time it will decrease. Furthermore, if I scroll down, you can see that I can vote for the next bow emission. For example, I voted for the W re pool. And then let's go back to the claim tab again. And then scrolling down here, you can see that I'm also ellegible to receive protocol revenues. Let's also see how to provide liquidity to a balancer through the oral finance user interface. The first step to provide liquidity. For example, let's provide liquidity in R and W. So I'll

search for the pool R E and W by typing R E. Then scrolling down at the top, I see the re pool. Click on this. From this page, you have several options. You can stake your re BPT token or you can single side add liquidity either with R E or W. To do that, you'll click on the button deposit in stake. I've already done that, so I'm not going to show you here. Then once you've done that, the next step is to claim the rewards. You can do this by clicking on the claim tab. Since I've already added liquidity to the re pool using a finance here under claimable rewards, I see a reward that I can claim under REF stable pool.

To claim a reward, I'll click, let's just say, click on all of it. And you can click claim rewards to claim the rewards. Now, I won't submit a transaction here since the amount of tokens that I can claim is virtually equal to zero. I'm just burning ETH if I were to submit a transaction to claim the rewards. But notice that I can claim the rewards for Bell, Aura, and RPL. In the example that I just showed you on balancer user interface and Aura user interface, here are the actual transactions that I sent on the main net. If you're curious on what contracts were called, what functions were called, and what parameters were passed, click on these links to see the details. These links will be included in the readme of the GitHub repo. For example, let's

click on one of these transaction to see what you'll see if you were to click on this link. So let's click on add liquidity transaction. This will take you to etherscan. Again, this transaction was to add liquidity to balancer. Here's the transaction ID. And if you wanted to see more details, you can see which account the transaction was initiated by, which contract it called, how the tokens were transferred. Further down, click on more details to see what function was called and what parameters were passed. These links to the transaction might be something that will interest you. If you need to know exactly how to interact with the balancer protocol or the Aura protocol.

So again, here are the example transactions, click on it to see the details. Let's go over the solution for how to add liquidity to balancer B2 AMM. The first thing that we'll do is pull in ref and W. So say if ref amount is greater than zero, then we'll say ref dot transfer from message.ender sender to this contract for the amount ref amount. We'll also approve the balancer B2 contract to pull in the ref from this contract. And which contract do we need to approve? Let's scroll up to see which contract that we need to call. Over here you can see that the bolt contract remember the bolt contract in balancer

B2 is a contract that will manage all of the tokens. This is a contract where all of the tokens will be locked. So we'll need to approve this contract. Okay, going back down. So, let's say ref dot approve address of the bolt bolt for the amount ref amount the amount that we're going to deposit. And then we'll do the same for W. Just simply change these parameters to W with amount and then change the token as well with. Okay, so that's the first step transferring the tokens in and then approving the balancer B2 vault contract to spend the tokens from this contract. Okay, what is the next step? The next step is to call

the internal function join. This function will add liquidity to the balancer B2B bulk contract. Here you can see the details on how to call this contract. We'll call the function called join pool with these parameters. If you're curious, you can check out this details and also look into the balancer B2 documentation. But for this exercise, you can treat this internal function like a magic function where if you pass in these inputs, then it will add liquidity to the balancer V2. The parameters that we'll need to pass are recipient, assets, and max amounts in.

assets will be the tokens that we'll add liquidity as and the address of the assets. The order of the token addresses are important and then max amounts in the amount of tokens that we're going to be adding. So let's copy this function. We'll need to prepare these parameters and then back inside our join function I'll paste this code. So we'll need to call the internal function join. Let's start with the recipient. Who will be the recipient of the LP token once free? Add ref and ref as liquidity. The recipient will be the caller message sender. Next, we'll prepare the parameters assets and max amounts in.

So, I'll paste them here for now. Okay. So, let's prepare the parameters address memory assets and max amounts in. Let's start with facets. This will be the address of the tokens. And the order of the tokens that we pass into this address array is important. The order that we'll need to pass is ref and then ref. So we'll initialize an array of addresses having the length two. New address length two and then say assets of zero will be ref say address of re and then the next one assets of one will be ref. Okay let's move on to max amounts in this will be equal to new in 256 of length 2. Then say max amount in

of zero will be the re amount re amount and then the next input will be web amount and then call the function join. Okay, the final step is to refund any tokens that was not added as liquidity. When we call the function join on the balancer B2 AMM, there's a chance that it didn't take in all of the tokens. We'll query the balance of tokens that are left over inside this contract and then send it over to message sender. Let's start with reint 256 ref bell balance of re in this contract. Ref dot balance of address this and then say if ref bell is greater than zero then we'll transfer this over

to message sender ref dot transfer to message sender for the amount ref bell. Then we'll do the same for W. Just change the variables. W Bell val and the token as well. W. Okay, that completes the exercise to join liquidity to add liquidity into balancer B2MM. Let's try executing this function against the test inside the terminal. I'll paste this command forge test. The file that we're testing is exercise balancer and the function that we're calling is called test join.

Okay, and our test passed. After adding liquidity, we get back approximately two BPT tokens. Let's go over the solution for how to exit liquidity from balancer B2M. Once we add liquidity to Balancer B2M and we want to pull out the tokens, then we'll exit the liquidity. First, we'll pull in the BPT token, the liquidity provider shares from message sender. And here, this BPT token is initialized over here. This BPT token refers to the liquidity provider token for the pool ref. transfer from message sender to this contract for the amount BPT amount.

And then the next step is to call the internal function called exit. This internal function hides the details of how to remove liquidity from the balancer B2 AMM. We will call a function called exit pool. And here are the parameters that you'll need to prepare for this exercise. You don't have to worry about the details. The only details that you'll need to worry about is making sure that these parameters are the right parameters. BPT amount, recipient, this will be the recipient of the tokens that are withdrawn. Assets, this will be the address of the tokens and min amounts out. Minimum amount of tokens that we expect to get back. Let's copy this function and then paste it here. Okay, let's start with BPT amount. BPT amount

will come from the input recipient. The recipient of the tokens that are withdrawn message sender. Then we also need to prepare a array of addresses and array of un 256. Let's start with assets for the ref pool. This will be an array of address of length two where the first address will be ref and the second address will be ref. New address array of address size two. Then assets of zero address of ref and assets of one will be address of ref. Min amounts out. For this exercise, we're only going to remove liquidity in re new unit 256 size 2. Min amounts out for the zero index

will be for the amount for our E. This will be min re amount out. And then for index one, this will be this will be zero. since we're removing liquidity all in re. Okay. And that completes this exercise. Now to test this function, I'll need to prep back the solution for the function join which will add liquidity. Okay. Let's now execute the test inside the terminal. Here's the command that I will execute. The file is exercise balancer and the test is called test exit. And our test pass for removing liquidity. We got back approximately 1.89 89 RE. Let's go over the solution for how to add liquidity to a balance for V2 through Aura Finance.

The function that we'll implement is called deposit. The first thing that we'll do is transfer R E from message sender. R E dot transfer from message.ender to this contract for the amount EF amount. Next, to deposit into our finance, we'll need to approve a contract called the deposit wrapper that is defined over here. Ref dot approve address of deposit wrapper for the amount re amount. To add liquidity through the oral finance, we'll need to call a function inside the deposit wrapper. Let's take a look at the interface for deposit wrapper. Scrolling up can see over here that the deposit wrapper is initialized with the

interface I reward pool deposit wrapper. Let's navigate to this file inside source under interface aura. There's an interface called I reward pool deposit wrapper. Click on this. Okay. And this is the function that we'll need to call to deposit liquidity into balancer B2 by our finance. So let's copy this. Go back to the function that we were working on. Then paste it here. The contract that we'll need to call is deposit wrapper and the function that we need to call is deposit single. Prepare these parameters. Okay, let's start with reward pool. The address of the reward pool. Let's scroll up to see what it is initialized as. It's initialized as a constant over here. So, let's change

this address reward pool. Next will be the address of the input token. The token that we're adding as liquidity. This will be our E. Next will be the input amount. The amount of token that we're adding re amount. And then next will be balancer pool ID. This will be bytes 32. Where can we get this balancer pool ID? Let's scroll up. The balancer pool ID. Here it is. Balancer pool ID ref. I'll copy this and then let's paste it here. And finally a parameter called request which will be a str from join pool request. Remember in the exercise for adding liquidity to a balancer there

was an internal function called join. Let's take a look at that function to see how to prepare this parameter. So under exercises under the contract balancer liquidity. I'm looking for a internal function called join. Here you can see how the parameter is prepared. Let's copy all of this and then back inside our aura liquidity contract. Let's paste this in. Then maybe we'll need to change the parameters inside here. Okay. So it looks like you'll need to prepare a parameter called assets and max amount in. Let's go to the solutions for the balancer liquidity exercise to see how these parameters were prepared.

Solutions balancer liquidity. How are the parameters prepared for assets and max amounts in okay here it is. I'll copy these and then back inside our exercise the exercise that we're working now. I'll paste these over here. So the assets will be R E and W and the amount will be R E amount and W amount. However, for this exercise, we're providing liquidity only in re. So W amount will be zero. Okay, so that's how you would add liquidity to balancer B2 by or finance. The next step is to refund RE if not all of the RE was added as liquidity. You'll first get the balance of RE remaining in this contract. ref bow is equal to re if dot

balance of this contract and then say if ref bow is greater than zero ref transfer to message sender transfer to message sender for the amount re and the final step is to return the amount of shares that was minted from auro finance for providing liquidity and the way we will do that is we'll first need to get an interface inside the finance interface aura and then click on I base reward pool 4626. Then here it says returns the balance of shares staked in this contract. The function that we'll need to call is called balance of on the contract with the interface I base

reward pool 4626. Okay. So going back to our contract and scrolling back up can see here that this contract called reward pool has the interface I base reward pool 4626. So say shares is equal to reward pool dot balance of address this. Notice that I'm not declaring the variable here since it's already declared as a return output. Okay. So that completes the function deposit. Let's try compiling this contract. Inside the terminal type forge build.

Okay. And our contract compiles. We'll be testing this function once we implement all of the functions. The other two functions that we'll need to implement are claiming rewards and then exiting liquidity. Once we add liquidity by the or finance, it's going to start occurring rewards which we can claim. To claim the rewards, we'll need to call the contract reward pool. The reward pool has a function called get rewards and it doesn't take any inputs. Calling this function will send any rewards that we can claim to the caller. When this contract calls get reward on reward pool, any reward token will be sent into this contract. And to transfer the rewards that this contract claimed, there's a function called transfer where only an authorized account can specify

the token and the destination. So all we have to do here is call reward pool.get reward. Let's try compiling this contract. Inside the terminal, type forge build. Okay. And our contract compiles. The last exercise in or finance is to remove liquidity through or finance. The first step is to call function called withdrawal and unwrap on the reward pool contract. Takes in two inputs amount the amount of shares to withdraw and a boolean field called claim. If this is set to true when withdrawing the tokens it will also claim the rewards. For the output it's going to return a boolean and it will be true if it successfully withdrew the tokens. So first step is to withdraw the

tokens. reward pool dot withdrawal and unwrap passing in shares and saying true to claim the rewards. It's going to return a boolean. It's going to return true if it was successful. Require that this call was successful with the error message. Let's say withdrawal failed. Once withdrawal is successful inside this contract, we'll have the BPT tokens. The BPT token, the liquidity provider token here will be the reb pool. The next step is to get this BPT balance and then call the balancer to remove liquidity. Unit 256 BPT val is equal to BPT dot balance of this contract. And then next we'll need to

remove liquidity directly from balancer B2. Let's check the solution for the exercise where we remove liquidity from balancer B2. inside under solutions, click on balancer liquidity and then look for a function called exit. Okay, here it is. So first they prepare some parameters and then call internal function called exit. I'm going to copy all this and then paste it here. So these two assets and min amounts out are the parameters that we need to prepare and then it calls an internal function called exit. Let's see what the internal function does. But here it is. then scrolling up to look for the internal function. Okay, here it is. I'll copy all of this and then paste it here.

Okay, and now let's go through these parameters. Make sure that they are the correct parameters. Let's start with assets. Assets will be ref and w. So that is correct. How about min amounts out? Since we're removing liquidity or in our E, this is correct. Min ref amount out which will come from the input and for will be zero. And then we call the function exit pull on the balancer vault contract. Pull ID is correct. Sender will be this contract here. Sender means the sender of the BPT token. And recipient this will be message. sender message. sender the address that is going to receive the re.

Then scrolling down further we have min amounts out and assets. And then finally BPT amount. This should be BPT bow. all of the BPT inside this contract. Okay, and that completes this exercise. Let's now execute a test. The test will test the function deposit get rewards and also exiting liquidity. Okay, here's the command that I will execute to execute the test. The file will be exercise aura and the test is called test deposit and exit. Okay, and our test passed. Let's take a look at the logs. deposit into our finance and we get back one pool shares. Call the function get rewards and we get some

rewards in bal token and aura. Then scrolling down after withdrawing liquidity we see that our re balance is roughly 0.999 re and we also have some rewards in balancer token and token. What is rocket pool's nab oracle? First of all, nab stands for net asset value. So the nav oracle is the net asset value of re. It's a oracle that will give the net asset value of re or in simple terms it will give the exchange rate between re and e. The equation is also simple nav.

This is equal to total e in rocket pool divided by total re supply. This total e in rocket pool contains amount of st ear earned rewards and any penalties. Okay. What's the difference between NAB, the exchange between RE and ETH given by the Rocket Pool Oracle and the market rate? What are the differences? NAB is the exchange rate that is given by the protocol by the Rocket Pool protocol and it is based on the equation above this equation over here. How about market rate? Well, the market rate is given by the market exchange rate. The market rate will slightly differ depending on your source. For example, getting the market rate from chain link might be slightly different from getting the

market rate from a centralized exchange such as Binance or a decentralized exchange such as unis swap. All of these are market exchange rates and the rate is based on the supply and demand of our E. When should you use one over the other? Well, here's a guideline. Pick the better of the two rates for trades. If you want a better deal, just pick the one that has a better exchange rate. If the exchange rate given by the rocket pool protocol is better than the market rate, then interact with the rocket pool to get the tokens, whether it be Raf or E. And if the market rate gives you a better deal, then swap your tokens on the market, either through centralized exchange or through decentralized exchange. So, pick the better of the two

rates. If you only want to trade the tokens, then when is NAV a more useful exchange rate to use? The answer is use NAV for long-term holdings. And the reason is because the market rate is going up and down frequently depending on the time that you get this exchange rate. The value that is calculated from the market rate might be significantly different. For example, if in 1 second the market rate spikes up by let's say 10%. Then depending on when you get this market rate, the value that is calculated from this market rate will also differ by 10%. However, the NAB exchange rate calculated by the protocol is a more stable way to calculate the value of RE. So for evaluation of long-term holding of REF, NAB will be a

more reliable way to calculate the value of RE. Let's look at a live example of fetching the NAB from the Rocket Pool's NAB Oracle. I'm inside the documentation for RocketPool and under the page called integrations. Inside here, I'm going to look for the contract address of the NAB Oracle. So let's search for NAV NAB. Okay. And then here it is scrolling down and then I'll click on this. This will take me to the Etherscan website and it also will take me to the function get exchange rate and that is the current exchange rate given by the rocket pool's nav oracle. Here this number has 18 decimals. Let's copy this and then divide this by 10^ the 18 to see what

the exchange rate is. I'm going to do that by opening a Python shell. Inside my terminal, I'll type Python. This will open my Python shell. Paste the number that we just copied over and then divide this by 1 1818. And we get back approximately 1.1255. And this is the exchange rate of 1 R to E. If one re was provided to the rocket pool protocol, they would give us back approximately 1.1255 E. Okay, let's go over the solution for how to get the exchange rate of one re into E. And to do this, I'm going to first navigate to the re contract inside the GitHub repo of RocketPool. Here we're inside the GitHub repo for the rocket pool. And I'm

looking at the re contract. Remember that inside this contract there are two functions. One function will get the exchange rate from E to R and the other function will get the exchange rate from R E back to E. So we have two functions. Get E if value and get R if value. Which function do we need to call? Let's read through the comments. Get E if value. Calculate the amount of E if backing the amount of our E. So for example, if we put in one re into here, it will give us back the amount of E that is backing one R E. Okay. So this looks like the function that we'll need to call for the solution. You can call this function passing in one re over here. There's

also another solution where this is handled inside this code over here. There's a function called get exchange rate which will call the function get if value passing in 18. Okay. So for this solution I'll call this function. Back inside our code we'll call the function return if dot and then paste the code get exchange rate. This will get the exchange rate of one re into E. Okay. So before we execute the test here I want to mention that I've also created a function to get the exchange rate of re into E from chain link. We'll call both of the function inside a test and then compare the exchange rates. Okay, here's

a test command. The file that we're testing is exercise R E. The function that we're testing is called test net. In the test passed, let's take a look at the logs. So the exchange rate E R E rate from rocket pool gives us approximately 1.125. If we were to give one R E to the rocket pool then it will give us back approximately 1.1255 E given that the rocket pool's minting and burning is available that it is enabled. How about if re exchange rate from chain link? So you can think about this exchange rate from chain link as the market price. The market price of one re back into E is approximately 1.12000. If you were to swap one R E on

the market, then you're probably going to get a exchange rate something close to this 1.12000 E. So in this case, assuming that the Rocket P's mint and burn are enabled, you should swap your RE back to E using the Rocket P contract. If the exchange rate on chain link was higher than rocketpool, then it would be the other way around. You should probably swap your re back into E using some decentralized exchange or any other centralized exchange. What is layer? I en layer is a protocol that allows you to reuse the staked E to secure other protocol or services. And what does this mean? Before I explain what this means, I first want to explain the problem.

What problem does Ethereum and other proof ofstake protocols have? and how layer solve these problems. So let's start with the problem. Imagine Ethereum without layer. We have smart contracts and these smart contracts are secured by the Ethereum network. The way Ethereum network is secured is by the proof ofstake consensus. Basically validators lock their Ethereum and validate transactions and propose new blocks. If they misbehave in one way or another, their Ethereum that they locked will be destroyed. On Ethereum, we also have a tokenized version of the Ethereum that is staked. For example, Lido SD and Rocket Pool R E. Users deposit Ethereum into their protocol and then the protocol will mint these tokens. The

protocol uses the Ethereum deposited by the users and then allocates it to a validator that they assign. Now, imagine that there's a new protocol or a service that requires decentralization and economic security. In other words, proof of stake. and they issue their own coin and here what I mean by a service for example is like a data availability service or price oracle bridge or rollup sequencer and etc. So we have some kind of service or a protocol that cannot be done by a smart contract. So these services cannot be secured by Ethereum since they are not smart contracts. They need to issue their own tokens to spin up a proof ofstake consensus. So now imagine a potential staker with a lot of

money. They can either use this money to buy ETH and then stake into the Ethereum network or they can use their money to buy this token to secure this service. But of course, this staker doesn't have infinite capital. So, he can only choose one stake into Ethereum or stake into this other service. Now, imagine that there are hundreds of these stakers. Each of them will have to decide either to stake into ETH or stake into another service or they might have enough capital to stake into both. But the point is their capital must be split between the two services. Proof of stake is secured by the amount of value that is staked. When stakers have to split their capital to stake some into this offchain service and some other to

Ethereum, it fragments economic security. For example, let's say that this staker had $100. They can either choose this $100 to stake Ethereum or to stake this other service or split this $100 to participate in proof of stake for both Ethereum and this service. But this $100 of economic security is split between Ethereum and this other service. So this is a problem of proof ofstake from the stakers perspective. But there's also a perspective from the protocol. For a new protocol, it's difficult to get the attention of potential stakers to stake tokens into their protocol over another protocol such as Ethereum. I lay there solves the problem of fragmentation of economic

security and the difficulty of bootstrapping economic security for new protocols by using stake thief or its derivatives LSTs as a staking token to secure these services and protocols. The way it works is let's say that a staker has some capital The first step is to either acquire ethereum or any of the LSDs such as rocket pool re and vital st. In the case that a staker acquired LSD, they simply deposit these LST into the IGEN layer protocol. On the other hand, if the user bought E, then he'll have to run a validator and then stake E through the IGEN layer. In this case, the withdrawal address will be managed by layer. What this means is that when this validator run by this staker

decides to exit the E out of Ethereum staking the Ethereum will be sent to a address that is managed by layer. So once this staker has some representation of staken E. The next step is that layer will be able to use these either the staked E or the AOST to secure these protocol. It's going to use the stake thief or some representation of the stake thief to secure these services. Hence, it is called reststake. It's reusing stake thief to secure these protocol. In return, these services and protocols will issue staking rewards.

And now the staking reward for this staker will be E for staking into E. And it's reusing the stake E to secure these protocols. So this staker will also earn the rewards from service one, service 2 and service 3. This staker will receive a higher reward but also faces a higher risk of either losing his stake thief or his LSD whichever one he used to restake. Since his stake thief or his LSDs are being used to secure service 1, two, and three, if any of them fail, then he will be penalized. he has a higher chance of losing his tokens compared to simply staking into the Ethereum protocol. How does a layer

work? There are three main participants. Service builders, operators, and stakers. Up until now, we refer to as service and protocols. These services are called ABS actively validated services in IGEN layer and they're basically what we discussed so far decentralized services built on the Ethereum that provides custom validation mechanisms of off-chain operations. So let's say that we have these ABS's decentralized services that want some kind of economic security. The first participant service builders will be the developers of these ABS's. Next we will have operators. People who are willing to run the services that these ABS developers wrote. These operators will

first register with the Igen layer protocol as operators and then they will also register to run these ABS's and then we have the staker. They are the ones that will lock their state def or LST into the IER protocol and then delegate these tokens over to the operator. So after they acquire ETH and then stake it into the Ethering protocol or obtain one of these LSTs, if they obtain a LST such as R E and SD, then they simply deposit into the IE layer protocol. If they were to provide E, then first they will run a valid later and then stake E through the IE layer protocol. Once the LST or the stake E is controlled by the IER protocol, they can now delegate their staked asset to

operator. They're picking the operator to use their staked asset to run one of these ABS's to earn these rewards. The rewards for running these ABS's are sent to the IER protocol. And both the operator that run these ABS's and the staker who has provided the economic security can claim these rewards. Here I'll explain some of the core contracts in IGEN layer and how stakers and operators can interact with these contracts. Let's start with a staker. A staker can decide to deposit any of their LSD tokens or other tokens supported by the IGEN layer. These tokens will be sent to the strategy manager contract which will have a

separate contract called strategy for each token. So we will have a strategy that manages our E, a strategy that manages SD, strategy that manages D and so on. The tokens will be locked in the strategy contract. The user will interact with the strategy manager contract. On the other hand, if the user decides to stake their Ethereum and run a validator through IGEN layer, then they'll first create a contract called IEN pods. Each user will have a dedicated pod contract. And these pod contracts will be managed by the pod manager. When the staker deploys the IG pod and then stakes his E, he will interact with the pod manager contract.

Once the staker has these staked asset deposited into the IGEN layer protocol, the next step is to delegate to an operator. Delegate these staked assets to an operator. The staker will interact with the delegation manager. And if you wanted to undelegate from an operator, he will also interact with this contract. Other cases where the staker will interact with this delegation manager is when this staker decides to withdraw his stake tokens. There's a waiting period once EQ withdrawal. Once this waiting period has elapsed, the staker will be able to withdraw his tokens. And lastly, the staker can claim rewards by interacting with the rewards coordinator contract. Next, let's take a look at how the operator will interact

with these contracts. The first thing the operator will have to do is register with the delegation manager. Register as an operator. Next, he will register which ABS's to run or he might change the ABS's around. So he might also dregister from a abs and then to claim rewards he will interact with the rewards coordinator contract rewards in a layer is submitted as a merkel tree route and it's helpful to know what this Merkel tree represent when you're claiming rewards. So here I'll explain how this Merkel tree is structured at the top will be the Merkel route where each of these will be some information about the earner. So let's say that we have n earners. Each of these earner will contain two data. Address of the

earner and token root. This token route will again be another route to a Merkel tree. For example, let's say that earner 2 can claim up to K tokens as reward. So again, this earner 2 will contain information about the address for earner 2 and the token route specific to earner 2. This token route is again a Merkel tree root. At the leaf will be some information about token. Let's say token one to K. And each of these will contain information about the address of the token and the cumulative earnings the amount of tokens that they have earned so far. To deposit re into IGEN layer, let's first pull in the re from message sender into this contract. Ref. Transfer

from message sender to this contract for the amount re amount. And then we'll approve the IG layer contract to spend the tokens from this contract. Ref.approve. Which contract do we need to approve? Remember, we need to deposit into the strategy manager contract. And what is the name of the strategy manager contract inside this contract? What do we name that contract? Scrolling up, you can see that the strategy manager is named as strategy manager. So, we need to approve this contract.

prove address of strategy manager for the amount re amount. Okay, the next step is to call deposit function inside the strategy manager. Scrolling up, let's navigate to the interface for the strategy manager. The interface is called I strategy manager. So inside the folder, I'm going to navigate to interfaces again layer I strategy manager. Okay. And here is the function that we'll need to call deposit into strategy. I'll copy this function signature and then paste it inside the code that we're currently working on.

Okay. And then call the function strategy manager dot deposit into strategy. Okay. And these are the parameters that we'll need to prepare. Strategy the address of the strategy. What is the address of the strategy that contains our E? You can see here that there's a variable called strategy that is initialized as igen there strategy for re. So this will be simply address of strategy. Next is token. Token is simple. It's re let's say address of re and then amount amount of re that we're going to deposit into layer. This is our amount the amount that we approve. Okay.

And then it's going to return the number of shares. Let's assign this to the variable that we're returning here, shares. Say shares is equal to. That completes this exercise. Let's try executing the test for calling the function deposit. Inside my terminal, here's the command that I will execute. Forge test with fork URL. The test is called exercise layer and the function that we're calling is called test deposit. Okay. And our test passed. Once we have our E locked inside there, the next step is to delegate our staked assets to our operator. The contract that we need to call is the delegation manager. Let's scroll up to see what the name of the delegation manager contract is. Okay, over here we have the contract

called delegation manager with the interface I delegation manager. Scrolling back down, we'll need to call the contract delegation manager. Okay. And what function do we need to call? Let's navigate to the interface for I delegation manager. Inside interface layer, click on I delegation manager. Okay. And let's look at some functions that we can possibly call. So we have delegate to undelegate Q withdraw and complete Q withdraw. Then we have other view functions. It looks like we'll need to call the function delegate to takes in a address of operator and then it also takes in a strct as a parameter which is defined over here and the approver salt. Let's copy all of this

and then paste it here. The function this is the function that we need to call. Let's start with the address of the operator. This is simple. The operator will come from input operator. Next is this strct input called approver signature and expiry which is a strct this strct over here. Let's copy this and then paste it here. For this exercise we're not using any signature so we can set this as an empty signature. And we're also not using expiry. So we'll set this as default value zero. And then approve our salt.

We're not using signatures. So we'll also set this as default bytes 32 uint 256. The signature with expiry struck is imported from the interface I delegation manager. So I'll need to prefix this with I delegation manager dot signature with expiry. Okay, that completes this exercise. Let's try executing this function. Here's the command that I will execute inside my terminal. The test file is exercise layer and the test function is test delegate. Great, our test passed. If you decide to withdraw your staked assets from layer, it takes two steps. Unddlegate and then this will cue the withdrawal and then after some

time has elapsed, you'll be able to complete the withdrawal. By calling the function undelegate, you will undelegate from the current operator and it will also automatically cue a withdrawal. The contract that we'll need to call is again delegation manager. Delegation manager. And what is the function that we'll need to call? Let's check the interface for I delegation manager. Inside here there's a function called undelegate and takes in a single input the address of the staker. We'll call undelegate. The address of the staker. This contract was the contract that called into layer. So this contract is the staker address this. Now going back to the I delegation manager interface.

You can see here that when we call the function on delegate, it returns an array of bytes 32 called withdrawal root. Let's assign this to the variable here. Withdrawal root. Now I'm not sure what this withdrawal route is used for. In our exercises, we won't be needing this. Here's a test command. The file to test is exercise layer. The function to call is test on delegate. Okay. And our test passed. Once we cue the withdrawal by calling the function on delegate, we'll have to wait some time. After we wait a certain time, we'll be able to actually withdraw the tokens from layer.

The amount of time that we'll have to wait is calculated from this function over here. Basically, it is the maximum of the protocol delay and the delay that is specific to each strategy that you've deposited into. The protocol delay is fetched by calling the function min withdrawal delay blocks from delegation manager. And to get the withdrawal delay specific to each strategy, you'll have to loop through the strategies that you deposited into and then call the function get withdrawal delay. In our application, we've only deposited into the re strategy. So we'll need to just get the withdrawal delay specific to re strategy. Take these two delays, protocol delay and the delay specific to re strategy, and then return the

maximum. This is the amount of waiting time that we'll have to wait after we cued a withdrawal before we can actually withdraw. Let's look at the inputs first. The function withdrawal will take in the operator, the operator that we're withdrawing the stakes from, the staked assets, the amount of shares to withdraw, and start block number. This start block number is the block number when we cued a withdrawal. In our application, when we call the function on delegate, it will automatically cue a withdrawal. This is handled by the function on delegate on the delegation manager. So the starting block where withdrawal is cued is the block when we call the function undelegate. Okay. So now let's actually withdraw the tokens.

To withdraw tokens again we'll need to call the contract delegation manager. And what function do we need to call? Let's check the interface for our delegation manager. Look for a function where we can actually withdraw the tokens. Here we have a function called Q withdraw. We've already cued a withdrawal. So let's scroll down. Okay. And then here I see a function called complete Q withdrawal. This is the function that we'll need to call. The inputs that we'll need to prepare is a little bit complex. Notice it takes in a strct called withdrawal which will be this strct over here.

Takes an array of tokens and then it has other inputs. Let's copy all of this and then let me explain one at a time. Then back inside our application, I'll paste the code and then I'll organize the code a little bit. Okay, so this is one of the strp input strrus that we'll need to prepare and the function that we'll eventually need to call is called complete q withdrawal. Let's first prepare the parameter withdrawal. Let's say I delegation manager dot withdrawal memory. I'll call this withdrawal is equal to and then initialize the str.

These are the parameters that we'll need to prep. Let's start with the staker. The address of the staker. This will be address this. And then address delegated to the address that we delegated to. This will be the address of the operator operator that we delegated to. And the operator that we undlegated from withdrawer the address that is going to withdraw. Address this. Nouns. Since we're not dealing with signatures, we're not going to need this. Set it to zero. Start block. This is the starting block where we cue the withdrawal. This comes from the input start block number. Start block num. Okay. And then we need to prepare an address array of strategies and an array of UN2 56 called shares.

Let's start with strategies. Address memory strategies is equal to new address. We've only deposited into one strategy, the re strategy. So we'll create an array of length one and then say strategies of zero is equal to address of the strategy the address of the re strategy. Next we'll prepare the shares say in 256 memory shares is equal to new in 256 size one and then say shares of zero is equal to the amount of shares that was specified by the input shares. to say shares. Now I have two

variables with the same name. Shares over here which represent the UN 256 and a shares over here which represent the array of UN 256. So let's rename this array of UN 256 as underscore shares underscore shares. Okay. And we're now ready to finish off the strct withdrawal. Strategies will be strategies. Shares will be underscore shares. Okay. The next step is to prepare parameters. Call the function complete withdraw. We prepare this parameter called withdraw. The strct withdraw. So this will be the strct that we just prepared.

Withdraw. Next is tokens. I just array of tokens that we're withdrawing. In our example, this will be our E. Let's copy this code and then rename it as tokens. This will be tokens. also a blank one since re is the only token that we're withdrawing. R and then change this to tokens. Okay, the next parameter middleware times index. We don't need this so we'll set it to zero and then receive as token. Do we want to receive our E? Yes. So I'll set it to true.

Okay, so that completes this exercise. Let's execute the test. Inside the terminal, we'll execute the command to test the function called test withdrawal on the file exercise layer. Okay. And our test pass. The last exercise in this contract is to claim rewards from layer. The contract that we'll need to call is the reward coordinator. Scrolling up. What is this contract named as inside our contract? Okay. Can see here that it is named rewards coordinator with the interface by rewards coordinator. So over here we'll need to call the contract rewards coordinator. Let's navigate to the rewards coordinator interface. Again this is inside

interfaces. I can there I rewards coordinator and let's look for a function where we will be able to claim a reward. Can see over here that there's a function called process claim. By calling this function tokens will be sent to the recipient. And then for the first input there is a custom input called rewards Merkel claim. Let's take a quick look at this strct. Okay, here it is. Rewards Merkel claim. Now recall that when rewards are submitted to the IGEN layer, it submits a Merkel route where the leaves contain two information the earner and the earner token root and the earner token root will be another Merkel root which will contain leaves of token and cumulative earnings. The

algorithm to generate the proof that a leaf is contained inside a Merkel tree is beyond the scope of this course. So for this exercise, just remember the Merkel tree structure when the rewards are submitted. And when we need to claim this reward, we'll need to pass in a Merkel tree proof that follows this structure. The way that this function claim rewards will be tested is inside the test under the folder layer, there's a test data that when parsed, it will generate the correct Merkel proof. This is copied from the code of IGEN layer. This data is parsed and then inside the test for layer. It will load that data.

You can see it over here and then pass it into our application contract. To test that we've actually called the layer contracts. Okay. So let's go back to our application. Claim rewards. You'll need to call the function process claim. The hard part the claim is already prepared from the input. So say claim and then the recipient address this. Okay. And that completes this exercise. Let's execute the test command. The file is exercise layer and the function that we're calling is test claim rewards. And the test passed. You can see from the logs that the reward token balances are greater than zero.

You might think that re only exists on the Ethereum mainet since Ethereum staking is something that you can do only on the mainet. So you might also think that the staking token like re only exists on the mainet. Harbor REF also exists on other chains such as Arbitum and Optimism. To check out the address of these tokens, head over to the official documentation. These RE token addresses might interest you. If you want to write an integration contract with RE but not on the mainet. For example, maybe you want to write an integration on the arbitrum or optimism chain. Then look for the token addresses from the official documentation. Here I want to explain about a theoretical arbitrage opportunity between E and R E.

It's based on two ideas. The first idea is that the value of R E relative to E generally increases over time. This is because over time R captures the value of E that was given as staking rewards. The other idea is finding a AMM where this re is sold at a discount. This in theory can be found on UNISAB B3 pools. When liquidity providers provide liquidity to UNISAB B3, when they provide R E as liquidity, they will have to set a price range. For example, providing liquidity all in re between the price range 3,100 and 3,200. Let's put these two ideas together. The first idea is that the value of re generally

increases over time and two liquidity providers on unis swap b3 are selling their re at a fixed price range. Over time the value of re will increase and it will surpass the price range where it is sold on unis swap b3. This means that re on unis swap b3 is sold at a discount. It is sold at a fixed price whereas the natural value of the re generally increases. So it will surpass that fixed price at some point. So this means that there might be a arbitrage opportunity. And we can test this out by running a simulation. What we're going to do is buy RE from Uniswap B3 and then immediately exchange that R E back to E using Rocketpole. We're swapping E into

R on Uniswap B3 since it is sold for a discount. And then we take that re convert it back into E using Rocketpole. This is our arbitrage opportunity. Let's test this out using Foundry. Inside the Foundry folder, under the folder called test, there's a file called deb unis swaw b3 arb. Open this. And let me quickly explain what's going on here before we execute the test. There's one function called test arb uni b3 to rocket bull. The first step is the setup. To run this hypothetical arbitrage opportunity, we first need to make sure that the contract r if has enough e. So this is what's going on here. Here it's sending E to the R E contract. If you remove this then this

simulation might fail. It might fail with the message saying insufficient E in our EF contract. Feel free to experiment around by adding this and then removing this. The next step is to make sure that this contract has enough W. This is the W that we're going to be trading on unis swap B3. And the next step is to swap this W for our E on U unis swap B3. Once this part is executed inside this contract, we'll have re. So the final step is to convert the re back into E using rocket pull. So the command that we'll execute is over here. I'll copy all of this and then inside the terminal I'll paste this command and then execute it. Okay. And a test passed. Now notice this should excite

you that we were able to pull off a hypothetical arbitrage opportunity. We put in one and we got back 1.0044. 0044 WF. Now, I want to mention three things before I end this video. The first two are limitations. One, here I emphasize that this is currently a hypothetical arbitrage opportunity. The reason is this is the amount of Eevee that you'll make. If you were to execute this on the main net, I'm sure that the gas cost will be higher than this. And then the other limitation is that before we executed this strategy, we had to make sure that our E contract had enough E in that contract. This is something outside of our control if you were to actually execute this on the main net.

So to pull off this arbitrage opportunity, two conditions must be met. The re contract must have enough E inside the contract and the gas cost must be low enough so that if you were to execute this arbitrage opportunity, then you'll make a profit. The final note that I want to mention here is that this opportunity, this arbitrage opportunity isn't specific to unis swap and rocket pole. The general arbitrage opportunity to look out for is to first find tokens are paired together where the tokens are similar to each other. However, one of the token is yield bearing and the other one is not. Since only one of the token is yield bearing over time, the value of that token will increase whereas the value of the other token will be fixed. And then you also

need to find the AMM where that yield bearing token is sold at a fixed price or some price range. Over time, since the yield bearing token is increasing in value, it will be sold at a discount. buy that token and then swap it somewhere else and hopefully make a arbitrage profit.