|
1 | 1 | # Yield Protocol Liquidator
|
2 | 2 |
|
3 |
| -Liquidates undercollateralized yDAI-ETH positions. |
| 3 | +Liquidates undercollateralized yDAI-ETH positions using Uniswap V2 as a capital source. |
4 | 4 |
|
5 |
| -On each new block, it calls the controller's `isCollateralized` method for each user |
6 |
| -that has previously opened a position. This is done by checking all `Borrowed` events |
7 |
| -and by compiling a database of addresses with currently open positions. |
| 5 | +``` |
| 6 | +Usage: ./yield-liquidator [OPTIONS] |
8 | 7 |
|
9 |
| -If `isCollateralized` returns `false`, it proceeds to call the `Liquidations` contract's |
10 |
| -`liquidate` function to claim the liquidation incentive. This can optionally be batched |
11 |
| -with the `buy` call to buy as much of the position as possible and liquidate it |
12 |
| -for DAI on 1inch/uniswap. |
| 8 | +Optional arguments: |
| 9 | + -h, --help |
| 10 | + -c, --controller CONTROLLER |
| 11 | + the Yield controller's address |
| 12 | + -l, --liquidations LIQUIDATIONS |
| 13 | + the Yield liquidation's address |
| 14 | + -u, --uniswap UNISWAP the DAI/WETH Uniswap V2 pair |
| 15 | + -f, --flashloan FLASHLOAN the address of your flashloan contract |
| 16 | + -U, --url URL the Ethereum node HTTP endpoint (default: http://localhost:8545) |
| 17 | + -p, --private-key PRIVATE-KEY |
| 18 | + your private key |
| 19 | + -i, --interval INTERVAL polling interval (ms) |
| 20 | + -F, --file FILE the file to be used for persistence (default: data.json) |
| 21 | + -m, --min-profit MIN-PROFIT |
| 22 | + the minimum profit per liquidation |
| 23 | +``` |
13 | 24 |
|
14 |
| -## CLI Options |
| 25 | +## Demo |
15 | 26 |
|
16 |
| -- Yield configuration with necessary addresses |
17 |
| -- Eth endpoint |
18 |
| -- Private key |
19 |
| -- start-block |
20 |
| -- should always buy? How much should it try to buy? |
21 |
| -- minimum amount |
| 27 | +### Local Testnet |
22 | 28 |
|
23 |
| -# Notes |
| 29 | +First we must clone the contracts and install the deps: |
24 | 30 |
|
25 |
| -- Generate corpus of addresses to monitor |
26 |
| -- Nonce manager |
27 |
| -- Gas price manager |
28 |
| -- Frontrunner |
29 |
| -- For an address: check if it can be liquidated -> liquidate |
30 |
| -- `trait Liquidator { fn monitor(user: Address); fn liquidate(user: Address);}` |
| 31 | +``` |
| 32 | +git clone https://github.com/yieldprotocol/yDai |
| 33 | +git checkout liquidator-testing |
| 34 | +yarn |
| 35 | +``` |
31 | 36 |
|
32 |
| -# Testing |
| 37 | +In one terminal, run ganache: `./scripts/ganache.sh` |
33 | 38 |
|
34 |
| -- Go to the yDAI directory and copy the `setup_liquidation.js` file to the `scripts/` dir |
35 |
| -- Deploy the contracts `npx truffle migrate --reset` |
36 |
| -- `cargo run` to launch the liquidator |
37 |
| -- Create a vault that can be liquidated `npx truffle exec scripts/setup_liquidation.js` |
38 |
| -- Watch the liquidator see that the vault became undercollateralized! |
| 39 | +In another terminal, deploy the contracts: `npx truffle migrate --reset` |
39 | 40 |
|
40 |
| -# Participating in an Auction |
| 41 | +This deploys MakerDAO, Yield, UniswapV2, [Multicall](https://github.com/makerdao/multicall) and the Flashloan contract. |
41 | 42 |
|
42 |
| -This leverages Uniswap's Flash Swaps. |
| 43 | +Now we run the liquidator (the Multicall address must be provided explicitly): |
43 | 44 |
|
44 |
| -1. borrow DAI from Uniswap (`swap(x, 0, liquidatorContractAddress, abi.encode(user address))`) |
45 |
| -2. Buy ETH at a discount from Yield Liquidation |
46 |
| -3. Send the required ETH to Uniswap s.t xy = k holds! |
| 45 | +``` |
| 46 | +RUST_LOG=yield_liquidator=trace cargo run -- --multicall D1Ed8059452f26360ba3DbD423cBfC955e9518cC |
| 47 | +``` |
47 | 48 |
|
48 |
| -# Demo |
| 49 | +Finally, you can create a liquidation opportunity by running `npx truffle exec scripts/create_liquidation_opportunity.js`. |
49 | 50 |
|
50 |
| -1. Deploy contracts |
51 |
| -2. Deploy a Uniswap, mint a 50 ETH CDP @ 150 spot and draw 7500 DAI |
52 |
| -3. As a user, put up 1 ETH collateral @ 150 spot, draw 150 yDAI |
53 |
| -4. Now price moves against us |
54 |
| -5. It gets detected by the liquidator -> triggers it |
55 |
| -6. The liquidation gets detected -> tries to buy it with a flash loan -> returns that it's too expensive |
56 |
| -7. Advance some time -> gets bought |
| 51 | +Note: re-creating the liquidation opportunity requires balancing the price on Uniswap |
| 52 | +so that you can get a good flash-swap price, by increasing the ratio between its DAI / ETH |
| 53 | +reserves. |
57 | 54 |
|
58 |
| -NB: Each time a flashloan is done, we're borrowing DAI from Uniswap and returning ETH, so we're pushing DAI's price up. If you want to run more examples, do `dai.mint(pair.address, xxx)` followed by `pair.sync()` to update the reserves & price. |
| 55 | +### Rinkeby |
59 | 56 |
|
60 |
| -# Bugs |
| 57 | +The contracts for Rinkeby have already been deployed. You can interact with them using the helper scripts explained below: |
61 | 58 |
|
62 |
| -1. receipt & unknown decoding from RPC |
| 59 | +First, we must setup our environment: |
| 60 | + |
| 61 | +``` |
| 62 | +git clone git@github.com:yieldprotocol/yield-cli.git |
| 63 | +yarn |
| 64 | +source config |
| 65 | +``` |
| 66 | + |
| 67 | +The `config` file will set your environment variables to allow you to mint tokens to Uniswap, set MakerDAO prices, and borrow or collateralize on Yield. |
| 68 | + |
| 69 | + |
| 70 | +Now we'll run the liquidator: |
| 71 | + |
| 72 | +``` |
| 73 | +RUST_LOG=yield_liquidator=trace cargo run -- \ |
| 74 | + -c ${CONTROLLER#"0x"} \ |
| 75 | + -l ${LIQUIDATIONS#"0x"} \ |
| 76 | + -u ${UNISWAP#"0x"} \ |
| 77 | + -f ${FLASH#"0x"} \ |
| 78 | + -p $PRIVATE_KEY \ |
| 79 | + -i 7000 \ |
| 80 | + -F rinkeby.json \ |
| 81 | + -U wss://rinkeby.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27 \ |
| 82 | + --min-profit 0 |
| 83 | +``` |
| 84 | + |
| 85 | +Finally, you can create a liquidation opportunity by running: |
| 86 | + |
| 87 | +``` |
| 88 | +./src/set_eth_price.js 200 |
| 89 | +./src/fund_uniswap.js 0 10000 |
| 90 | +./src/borrow.js 1 166 |
| 91 | +./src/set_eth_price.js 175 |
| 92 | +``` |
| 93 | + |
| 94 | +## How it Works |
| 95 | + |
| 96 | +On each block: |
| 97 | +1. Checks if any of our submitted transactions have been mined |
| 98 | +2. Updates our dataset of borrowers debt health & liquidation auctions with the new block's data |
| 99 | +3. Trigger the auction for any undercollateralized borrowers |
| 100 | +4. Try participating in any auctions which are worth buying |
| 101 | + |
| 102 | +## Known Bugs |
| 103 | + |
| 104 | +1. receipt & unknown decoding from RPC? |
63 | 105 | 2. too low nonce when used from the outside
|
64 | 106 | 3. how to find uniswap situation. should price go up or down? how do we know? replace error with proper warning
|
0 commit comments