-
Notifications
You must be signed in to change notification settings - Fork 2
/
transcript.txt
41 lines (21 loc) · 9.74 KB
/
transcript.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Welcome back. At this point, your Titanoboa skills are getting outstanding. You're absolutely ready to run the most sophisticated forms of Llama Lend liquidation. So the next few units are going to get a little bit advanced. Don't worry, we'll introduce the remaining concepts you need to know in this unit, which we call “Pure Liquidation.”
For this, and the next few units, we got to say goodbye to our VyperWifHat token. Instead, we're going to be working off of this repository written by our good friend, Macket. Macket’s a member of the Curve team, and to the `curvefi/liquidation-demo` repository has uploaded a few great examples of how to perform more advanced liquidations.
We'll be covering the simplest for this one to show off how it works. This is the `pure-liquidation-example.py` and that serves as the basis for the full and partial liquidation for upcoming videos. We'll start it running over here and you can see here the `pure-liquidation-example.py` file. Now, if you're a vim maximalist like myself, you might enjoy working with pure Python files, but don't worry. We're going to be taking all of this and rewriting it within a Jupyter notebook to be able to highlight some of the advantages of Boa. Of course, with Boa, you can play nicely with Jupyter, which means we can actually chart this, and for this video you'll be able to see better what's going on because a lot of things are happening here.
You'll notice one of the things you can catch right off the bat line 39 here, this is working with WBTC. And on the right hand side you can see the borrower health is just slowly getting eroded down to nearly zero, at which point a pure liquidation is happening. What is a pure liquidation? What does this all mean? Let's show this off.
Let's move to our Jupyter notebook because this a bit more familiar. If you notice, this structure of this is pretty similar to all the previous units., so we'll just talk through quickly at a high level what you need to know. You'll probably recognize the `%reload_ext boa.ipython`. This is necessary for running some of the Vyper cell magic from later. In the second cell is a slightly new concept that you might not have noticed before.
If you need to work with addresses within Titanoboa and generate them, it's very easy to type `boa.env.generate_address()` to deterministically come up with new addresses that you can work with. This is a nice feature of Macket’s scripts. Basically, instead of having everything happening from the EOA address like last time, we're going to be running external liquidations in this case.
There's a user, `BORROWER` that is taking out the loan, a different `TRADER` that's manipulating the market or trading the market, whatever you want to call it, and a `LIQUIDATOR` that is going to be responsible for performing this hard liquidation on the borrower. It's kind of more realistic to divide these up. We hide some helper functions here to help us with graphing, and this part should look familiar.
`dummy_oracle.deploy()` using the `ADMIN` address and setting the initial price equal to the Bitcoin price, which is around $65,000 as of the time of this shooting. And then we're creating a brand new Llama Lend vault. So there's only going to be one loan within this vault from a different borrower. In this case, it's still the `ADMIN` who holds the keys to this, and in fact the `ADMIN` is going ahead and depositing. We made one tweak here with our scripts where we are relying on this `load_from_impl()` that we showed off in prior videos. But if you actually look at the vault implementations here, it's using a different concept. It's loading the ABI directly. In this case, the script is relying on several interfaces `CurveRouter.json` for example.
For example, within our script we're pulling it from Etherscan. But if you don't have an Etherscan key, or don't want to get one, you could try Macket’s script, which is just pulling the ABI without needing things like the one second delay to avoid triggering the Etherscan API limits. The `ADMIN` has deposited $10 million crvUSD, so there's plenty to work with in this vault.
And now a `BORROWER` has come along and created a loan. So using `boa.env.prank()` to serve as the borrower, it's creating a much safer 30 bands, and you'll see next as the trader goes through and tries to change the price, how safe this actually is. So even though they’ve max borrowed at the price of 65,000 and they'll be safe from around like 44,000, give or take, to about 64,000, it's still kind of right at the bleeding edge.
We know nowadays crypto markets do nothing but dump, dump, dump. So let's bring in the `TRADER` to run this dumping because here's where the script gets interesting in our opinion. So the `TRADER` is getting a little bit of crvUSD and WBTC to work with. What this script here is doing is pretty cool. It's a `while` loop, so it's running the entire time, as long as the health of the `BORROWER` is above zero. This is a key concept because liquidations cannot happen while the borrower’s health is above zero. If you're borrowing from Llama Lend, you just got to keep an eye on that health number. Don't pay too much attention because health can actually degrade below zero at many different points within or below these liquidation bands.
So what this here is doing is it's looking at the target price for the trades, and it's doing it in reference to `p_down`, in other words, the bottom of the user's range. So essentially, as long as the price is above the bottom of the user's bands, it's going to keep driving the price down and then once it falls around that `p_down` range, it's going to just keep fluctuating up and down by about 1%.
That's what this `100 // 99` and `99 // 100` using integer division is doing. Then of course we fast forward 600 seconds as we saw previously, because we need to give the oracle time to catch up. Then it runs this trade directly on the AMM. The entire process looks a bit like this. You can see the price, shown in blue, starts at this higher value as it gets down to the bottom of the user's band range... so we start around $64K and, on this log scale, around $48K ... and then it just kind of moves up and down, back and forth, back and forth, allowing trading to happen around this price. And you can see the trades pump, dump pump, dump pump, dump, pump, dump, in amounts around $1,000 back and forth signified by the green.
So that's all that's happening here. And in order to do this, the user's health is just very steadily declining. And you'll notice this takes about 150 trades time 600 seconds apiece. In other words, in the worst possible circumstances for this user, they survived quite a long time at this fairly safe `n=30` bands. But at the end of it they end up like this.
So this is their collateral chart from before. We notice that all the collateral up to the max price has been erased. They're sitting just in this final band. They got a little bit of, a little bit of WBTC left, but everything else has been converted to $crvUSD. So along comes a liquidator to run the liquidation. Let's look at the absolute state of the market at this point.
They’re in what we’d consider an unhealthy user state. At this point, their state is on the left here and the debt is on the right. The debt is, at this point, completely dwarfed by the amount that's been converted to collateral. And this is where we're able to run what we call a “Pure Liquidation” because if this had not had the soft liquidation mechanism, you would see a lot more Bitcoin collateral and the crvUSD would not be enough to cover it.
But in this case, there's enough crvUSD to cover the debt. Because the user is in an unhealthy state, it's entirely possible just to pay off the debt using this, and return all the rest to the user. This is signified here. The user's unhealthy state is a small amount of Bitcoin, mostly $50,000 worth of crvUSD, $49,000 worth of debt.
If you look at the delta between this, that is the current Bitcoin price times the amount of Bitcoin, add the crvUSD, there is about $1,700 on the table for whoever runs this liquidation. Because it's in this pure state, because there's no need to convert wBTC. You can just go ahead and run it. all you need to do with this liquidator comes along, calls the `liquidate()` function, calls the user state, which they grabbed from up here.
`controller.user_state()` gives the key details of this `BORROWER` loan. It returns four values. The first three of which are the current amount of collateral, the current amount of collateral that's been converted to stablecoin, and the overall debt. The fourth is the number of bands. So we're just passing the amount of stablecoin, sending it from the `LIQUIDATOR` account.
Only two arguments and a pure liquidation happened. What's cool about this is the liquidator didn't have to have any WBTC, didn't have to have any crvUSD. They were able to run a pure liquidation just with enough Ethereum in their wallet to pay for gas, and their final balance is a little bit of Bitcoin, a little bit of crvUSD, and the value of this is ~$1700, the exact same as we saw above, ~$1700.
At this point, the user's loan is gone. If you look at the `controller.user_state()`, there's no loan that yet exists and the user is out of there. Got absolutely nothing. So liquidated user state: nothing, nothing, nothing, but at least no debt. That's it. That is a “Pure Liquidation.” Pretty cool. In the next unit though, we're going to go through the more complicated case where, what if the user is in an unhealthy state, but it's not quite covered by the crvUSD so you're going to have to convert some of the Bitcoin into crvUSD to run the liquidation. For now, hopefully you're going to be able to run this in the wild and maybe make a little bit of money. Not too bad. Keep an eye out for the next dump and we hope you stay safe.