diff --git a/core/README.md b/core/README.md index 4d652ec39..60ad3981d 100644 --- a/core/README.md +++ b/core/README.md @@ -46,6 +46,42 @@ The process of adding new collaterals depends on the token type used. This is du - if the script terminates with an error, please submit the report to the repository at https://github.com/sidestream-tech/unified-auctions-ui via an issue so that the support could be added. - Read more about the collateral oracle configurations at `./README.md#collateral-oracle-configs` +### Onboarding not yet deployed collateral + +When a completely new collateral type support is being prepared, we need to ensure that it will work even before the Maker Protocol is changed via a [`spell`](https://docs.makerdao.com/smart-contract-modules/governance-module/spell-detailed-documentation). Usually a new spell is prepared in the [spells-mainnet](https://github.com/makerdao/spells-mainnet/pulls) repository. When it is there we need to fork the repository, compile the spell and deploy it into the hardhat fork. Currently the setup is as follows: + +1. `rsync` or clone the repo to the desired x86 machine (tested with Docker 19.03.12 on Ubuntu 20.04) +2. `cd` into the `core/simulations/docker` and run `docker-compose up` to start the hardhat fork in one container and another container with installed [`dapp-tools`](https://github.com/dapphub/dapptools) +3. Shell into the `spells` container + - List avialble containers `docker container ls` (copy `CONTAINER ID` of the `docker_spells`) + - Shell into the container `docker exec -it 277a8d793341 sh` +4. Fix future `Invalid argument` `nix` error via `echo 'filter-syscalls = false' >> /etc/nix/nix.conf` +5. Open `nix` shell with useful tools `nix-shell -p cacert cachix curl git jq nix gnumake nano` +6. Update `dapp --version` to the supported version (currently 0.35.0) + - Install `duppgrade` via `curl https://rari-capital.github.io/duppgrade/install | bash` + - Execute `duppgrade` and wait +7. Clone branch containing the spell + - Clone the repo, eg `git clone https://github.com/makerdao/spells-mainnet spells && cd spells` + - Checkout correct branch `git checkout CES-795` +8. Fetch all libraries (that are linked via git submodules) using `dapp update` +9. Create keystore (that will be used by dapp-tools) + - Set hardhat private key into the file `echo 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' > ../private-key` + - Set password `echo '' > ../key-password` + - Import key to create a keystore folder `(printf "\n\n" && cat) | geth account import --datadir /root ../private-key` + - Press enter to finish the process +10. Prepare env vars + - `export ETH_KEYSTORE="/root/keystore"` + - `export ETH_PASSWORD="/root/key-password"` + - `export ETH_RPC_URL=http://core:8545` + - `export ETH_FROM="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"` - the address of the key from above + - `export ETH_GAS=3000000` - might need to be adjusted based on the `make estimate` output + - `export ETH_GAS_PRICE=1000000000000` +11. Compile the spell via `make` +12. Deploy the spell via `dapp create DssSpell` +13. Copy the bitecode of the spell into the `core/bytecode/compiledSpells.json` file, which will automatically update the `Onboard new collateral` simulation +14. Run `Onboard new collateral` locally to deploy compiled bytecode and execute the spell, create vault, liquidate vault to create auction +15. Run keeper and frontend against the simulation to validate that it worked + ### Collateral oracle configs Each collateral has the source where its price is fetched from. These values are stored on the blockchain, however they are not exposed via public access methods. diff --git a/core/bytecode/compiledSpells.json b/core/bytecode/compiledSpells.json new file mode 100644 index 000000000..d6d0caa58 --- /dev/null +++ b/core/bytecode/compiledSpells.json @@ -0,0 +1,3 @@ +{ + "RETH-A onboarding": "6101006040523480156200001257600080fd5b5062278d004201604051620000279062000212565b604051809103906000f08015801562000044573d6000803e3d6000fd5b5073da0ab1e0017debcd72be8599041a2aa3ba7e740f73ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b815260040162000092906200032f565b60206040518083038186803b158015620000ab57600080fd5b505afa158015620000c0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e69190620002dd565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1660601b815250508160c081815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250506040516024016040516020818303038152906040527f61461954000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060019080519060200190620001f592919062000220565b50600080829050803f915081608081815250505050505062000398565b6111a780620014b383390190565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200026357805160ff191683800117855562000294565b8280016001018555821562000294579182015b828111156200029357825182559160200191906001019062000276565b5b509050620002a39190620002a7565b5090565b5b80821115620002c2576000816000905550600101620002a8565b5090565b600081519050620002d7816200037e565b92915050565b600060208284031215620002f057600080fd5b60006200030084828501620002c6565b91505092915050565b7f4d43445f50415553450000000000000000000000000000000000000000000000815250565b6000602082019050620003456000830162000309565b919050565b600062000357826200035e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b62000389816200034a565b81146200039557600080fd5b50565b60805160a05160601c60c05160e05160601c6110a86200040b600039806104a4528061053352806106e9528061078f5250806102f552806106425250806102d1528061035752806103fc528061056f52806107cb528061086d525080610331528061059052806107ec52506110a86000f3fe608060405234801561001057600080fd5b50600436106100ce5760003560e01c80637284e4161161008c578063ae8421e111610066578063ae8421e1146101cd578063b0604a26146101eb578063f7992d85146101f5578063fe7d47bb14610213576100ce565b80637284e416146101875780638456cb59146101a557806396d373e5146101c3576100ce565b8062a7029b146100d35780630a7a1c4d146100f15780634665096d1461010f57806351973ec91461012d57806351f910661461014b5780636e832f0714610169575b600080fd5b6100db610231565b6040516100e89190610d9f565b60405180910390f35b6100f96102cf565b6040516101069190610d02565b60405180910390f35b6101176102f3565b6040516101249190610e79565b60405180910390f35b610135610317565b6040516101429190610dc1565b60405180910390f35b61015361032f565b6040516101609190610d84565b60405180910390f35b610171610353565b60405161017e9190610d69565b60405180910390f35b61018f6103f8565b60405161019c9190610df7565b60405180910390f35b6101ad6104a2565b6040516101ba9190610ddc565b60405180910390f35b6101cb6104c6565b005b6101d561062d565b6040516101e29190610d69565b60405180910390f35b6101f3610640565b005b6101fd610863565b60405161020a9190610e79565b60405180910390f35b61021b610869565b6040516102289190610e79565b60405180910390f35b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102c75780601f1061029c576101008083540402835291602001916102c7565b820191906000526020600020905b8154815290600101906020018083116102aa57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b73da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e832f076040518163ffffffff1660e01b815260040160206040518083038186803b1580156103bb57600080fd5b505afa1580156103cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f391906109ed565b905090565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637284e4166040518163ffffffff1660e01b815260040160006040518083038186803b15801561046057600080fd5b505afa158015610474573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061049d9190610a57565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260009054906101000a900460ff1615610516576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050d90610e19565b60405180910390fd5b6001600260006101000a81548160ff0219169083151502179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663168ccd677f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060016000546040518563ffffffff1660e01b81526004016105d39493929190610d1d565b600060405180830381600087803b1580156105ed57600080fd5b505af1158015610601573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061062a9190610a16565b50565b600260009054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000000000004211156106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069a90610e59565b60405180910390fd5b60008054146106e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106de90610e39565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636a42b8f86040518163ffffffff1660e01b815260040160206040518083038186803b15801561074d57600080fd5b505afa158015610761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107859190610a98565b42016000819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346d2fbbb7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060016000546040518563ffffffff1660e01b815260040161082f9493929190610d1d565b600060405180830381600087803b15801561084957600080fd5b505af115801561085d573d6000803e3d6000fd5b50505050565b60005481565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663bf0fbcec6000546040518263ffffffff1660e01b81526004016108c69190610e79565b60206040518083038186803b1580156108de57600080fd5b505afa1580156108f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109169190610a98565b905090565b60008151905061092a81611044565b92915050565b600082601f83011261094157600080fd5b815161095461094f82610ec1565b610e94565b9150808252602083016020830185838301111561097057600080fd5b61097b838284611000565b50505092915050565b600082601f83011261099557600080fd5b81516109a86109a382610eed565b610e94565b915080825260208301602083018583830111156109c457600080fd5b6109cf838284611000565b50505092915050565b6000815190506109e78161105b565b92915050565b6000602082840312156109ff57600080fd5b6000610a0d8482850161091b565b91505092915050565b600060208284031215610a2857600080fd5b600082015167ffffffffffffffff811115610a4257600080fd5b610a4e84828501610930565b91505092915050565b600060208284031215610a6957600080fd5b600082015167ffffffffffffffff811115610a8357600080fd5b610a8f84828501610984565b91505092915050565b600060208284031215610aaa57600080fd5b6000610ab8848285016109d8565b91505092915050565b610aca81610f66565b82525050565b610ad981610f78565b82525050565b610ae881610f84565b82525050565b6000610af982610f2e565b610b038185610f44565b9350610b13818560208601611000565b610b1c81611033565b840191505092915050565b600081546001811660008114610b445760018114610b6a57610bae565b607f6002830416610b558187610f44565b955060ff198316865260208601935050610bae565b60028204610b788187610f44565b9550610b8385610f19565b60005b82811015610ba557815481890152600182019150602081019050610b86565b80880195505050505b505092915050565b610bbf81610fb8565b82525050565b610bce81610fdc565b82525050565b6000610bdf82610f39565b610be98185610f55565b9350610bf9818560208601611000565b610c0281611033565b840191505092915050565b6000610c1a601283610f55565b91507f7370656c6c2d616c72656164792d6361737400000000000000000000000000006000830152602082019050919050565b6000610c5a602583610f55565b91507f54686973207370656c6c2068617320616c7265616479206265656e207363686560008301527f64756c65640000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000610cc0601983610f55565b91507f5468697320636f6e7472616374206861732065787069726564000000000000006000830152602082019050919050565b610cfc81610fae565b82525050565b6000602082019050610d176000830184610ac1565b92915050565b6000608082019050610d326000830187610ac1565b610d3f6020830186610adf565b8181036040830152610d518185610b27565b9050610d606060830184610cf3565b95945050505050565b6000602082019050610d7e6000830184610ad0565b92915050565b6000602082019050610d996000830184610adf565b92915050565b60006020820190508181036000830152610db98184610aee565b905092915050565b6000602082019050610dd66000830184610bb6565b92915050565b6000602082019050610df16000830184610bc5565b92915050565b60006020820190508181036000830152610e118184610bd4565b905092915050565b60006020820190508181036000830152610e3281610c0d565b9050919050565b60006020820190508181036000830152610e5281610c4d565b9050919050565b60006020820190508181036000830152610e7281610cb3565b9050919050565b6000602082019050610e8e6000830184610cf3565b92915050565b6000604051905081810181811067ffffffffffffffff82111715610eb757600080fd5b8060405250919050565b600067ffffffffffffffff821115610ed857600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115610f0457600080fd5b601f19601f8301169050602081019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610f7182610f8e565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610fc382610fca565b9050919050565b6000610fd582610f8e565b9050919050565b6000610fe782610fee565b9050919050565b6000610ff982610f8e565b9050919050565b60005b8381101561101e578082015181840152602081019050611003565b8381111561102d576000848401525b50505050565b6000601f19601f8301169050919050565b61104d81610f78565b811461105857600080fd5b50565b61106481610fae565b811461106f57600080fd5b5056fea2646970667358221220d4003e0481e94d82c34994140a0f4611ad2ba0fd75eea6e586fcf2bed552942764736f6c634300060c0033608060405234801561001057600080fd5b50611187806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063614619541461005c5780636e832f07146100665780637284e41614610084578063bf0fbcec146100a2578063f99e36bc146100d2575b600080fd5b6100646100dc565b005b61006e6101b5565b60405161007b9190610d91565b60405180910390f35b61008c6101ba565b6040516100999190610dac565b60405180910390f35b6100bc60048036038101906100b791906108f5565b6101d6565b6040516100c99190610f30565b60405180910390f35b6100da6102a5565b005b738de6ddbcd5053d32292aaa0d2105a32d108484a66335329d4c426100ff6101b5565b6040518363ffffffff1660e01b815260040161011c929190610f4b565b60206040518083038186803b15801561013457600080fd5b505af4158015610148573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061016c91906108cc565b6101ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101a290610e7f565b60405180910390fd5b6101b36102a5565b565b600090565b6040518060a00160405280606e81526020016110e4606e913981565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff1682111561020c57600080fd5b738de6ddbcd5053d32292aaa0d2105a32d108484a663d255745683426102306101b5565b6040518463ffffffff1660e01b815260040161024e93929190610f74565b60206040518083038186803b15801561026657600080fd5b505af415801561027a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029e919061091e565b9050919050565b6102ad610314565b738de6ddbcd5053d32292aaa0d2105a32d108484a6635f3a7dd76040518163ffffffff1660e01b81526004016102e290610e1c565b60006040518083038186803b1580156102fa57600080fd5b505af415801561030e573d6000803e3d6000fd5b50505050565b738de6ddbcd5053d32292aaa0d2105a32d108484a6637571a78e604051806102a001604052807f524554482d410000000000000000000000000000000000000000000000000000815260200173ae78736cd615f374d3085123a210448e74fc639373ffffffffffffffffffffffffffffffffffffffff16815260200173c6424e862f1462281b0a5fac078e4b63006bdebf73ffffffffffffffffffffffffffffffffffffffff1681526020017327ca5e525ea473ed52ea9423cd08ccc081d96a9873ffffffffffffffffffffffffffffffffffffffff16815260200173c59b62afc96cf9737f717b5e5815070c0f15439673ffffffffffffffffffffffffffffffffffffffff16815260200173ee7f0b350aa119b3d05dc733a4621a81972f7d4773ffffffffffffffffffffffffffffffffffffffff168152602001600115158152602001600115158152602001600115158152602001620f424060050281526020016103e8600f028152602001620f4240600202815260200161051481526020016b033b2e3ca65dca26e20d5eda8152602001612af881526020016113888152602001611c2081526020016111948152602001614268815260200160fa81526020016103e88152506040518263ffffffff1660e01b81526004016104f99190610f14565b60006040518083038186803b15801561051157600080fd5b505af4158015610525573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a663d0bab93373c59b62afc96cf9737f717b5e5815070c0f154396605a6126ac6040518463ffffffff1660e01b815260040161057b93929190610d5a565b60006040518083038186803b15801561059357600080fd5b505af41580156105a7573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a663b085f237620f4240600502620f42406003026170806040518463ffffffff1660e01b81526004016105f493929190610e3c565b60006040518083038186803b15801561060c57600080fd5b505af4158015610620573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66319d900a173ae78736cd615f374d3085123a210448e74fc63936040518263ffffffff1660e01b815260040161066f9190610e9f565b60006040518083038186803b15801561068757600080fd5b505af415801561069b573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66319d900a173ee7f0b350aa119b3d05dc733a4621a81972f7d476040518263ffffffff1660e01b81526004016106ea9190610df5565b60006040518083038186803b15801561070257600080fd5b505af4158015610716573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66319d900a173c6424e862f1462281b0a5fac078e4b63006bdebf6040518263ffffffff1660e01b81526004016107659190610dce565b60006040518083038186803b15801561077d57600080fd5b505af4158015610791573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66319d900a17327ca5e525ea473ed52ea9423cd08ccc081d96a986040518263ffffffff1660e01b81526004016107e09190610ec6565b60006040518083038186803b1580156107f857600080fd5b505af415801561080c573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66319d900a173c59b62afc96cf9737f717b5e5815070c0f1543966040518263ffffffff1660e01b815260040161085b9190610eed565b60006040518083038186803b15801561087357600080fd5b505af4158015610887573d6000803e3d6000fd5b50505050565b60008151905061089c816110b5565b92915050565b6000813590506108b1816110cc565b92915050565b6000815190506108c6816110cc565b92915050565b6000602082840312156108de57600080fd5b60006108ec8482850161088d565b91505092915050565b60006020828403121561090757600080fd5b6000610915848285016108a2565b91505092915050565b60006020828403121561093057600080fd5b600061093e848285016108b7565b91505092915050565b61095081610fd8565b82525050565b61095f81610fd8565b82525050565b61096e81610fea565b82525050565b61097d81610fea565b82525050565b61098c81610fea565b82525050565b61099b81610ff6565b82525050565b6109aa8161103b565b82525050565b6109b98161104d565b82525050565b6109c88161105f565b82525050565b60006109d982610fab565b6109e38185610fb6565b93506109f3818560208601611071565b6109fc816110a4565b840191505092915050565b7f4d43445f4a4f494e5f524554485f410000000000000000000000000000000000815250565b7f5049505f52455448000000000000000000000000000000000000000000000000815250565b6000610a60600683610fc7565b91507f312e31342e3400000000000000000000000000000000000000000000000000006000830152602082019050919050565b7f524554482d410000000000000000000000000000000000000000000000000000815250565b6000610ac6601483610fb6565b91507f4f757473696465206f666669636520686f7572730000000000000000000000006000830152602082019050919050565b7f5245544800000000000000000000000000000000000000000000000000000000815250565b7f4d43445f434c49505f524554485f410000000000000000000000000000000000815250565b7f4d43445f434c49505f43414c435f524554485f41000000000000000000000000815250565b6102a082016000820151610b826000850182610992565b506020820151610b956020850182610956565b506040820151610ba86040850182610956565b506060820151610bbb6060850182610956565b506080820151610bce6080850182610956565b5060a0820151610be160a0850182610956565b5060c0820151610bf460c0850182610983565b5060e0820151610c0760e0850182610983565b50610100820151610c1c610100850182610983565b50610120820151610c31610120850182610d3c565b50610140820151610c46610140850182610d3c565b50610160820151610c5b610160850182610d3c565b50610180820151610c70610180850182610d3c565b506101a0820151610c856101a0850182610d3c565b506101c0820151610c9a6101c0850182610d3c565b506101e0820151610caf6101e0850182610d3c565b50610200820151610cc4610200850182610d3c565b50610220820151610cd9610220850182610d3c565b50610240820151610cee610240850182610d3c565b50610260820151610d03610260850182610d3c565b50610280820151610d18610280850182610d3c565b50505050565b610d2781611020565b82525050565b610d3681611020565b82525050565b610d4581611020565b82525050565b610d548161102a565b82525050565b6000606082019050610d6f6000830186610947565b610d7c60208301856109b0565b610d8960408301846109bf565b949350505050565b6000602082019050610da66000830184610965565b92915050565b60006020820190508181036000830152610dc681846109ce565b905092915050565b6000604082019050610de260008301610a07565b610def6020830184610947565b92915050565b6000604082019050610e0960008301610a2d565b610e166020830184610947565b92915050565b60006020820190508181036000830152610e3581610a53565b9050919050565b6000608082019050610e5060008301610a93565b610e5d6020830186610d2d565b610e6a6040830185610d2d565b610e7760608301846109a1565b949350505050565b60006020820190508181036000830152610e9881610ab9565b9050919050565b6000604082019050610eb360008301610af9565b610ec06020830184610947565b92915050565b6000604082019050610eda60008301610b1f565b610ee76020830184610947565b92915050565b6000604082019050610f0160008301610b45565b610f0e6020830184610947565b92915050565b60006102a082019050610f2a6000830184610b6b565b92915050565b6000602082019050610f456000830184610d1e565b92915050565b6000604082019050610f606000830185610d4b565b610f6d6020830184610974565b9392505050565b6000606082019050610f896000830186610d4b565b610f966020830185610d4b565b610fa36040830184610974565b949350505050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610fe382611000565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600064ffffffffff82169050919050565b600061104682611020565b9050919050565b600061105882611020565b9050919050565b600061106a82611020565b9050919050565b60005b8381101561108f578082015181840152602081019050611074565b8381111561109e576000848401525b50505050565b6000601f19601f8301169050919050565b6110be81610fea565b81146110c957600080fd5b50565b6110d581611020565b81146110e057600080fd5b5056fe323032322d31302d3132204d616b657244414f20457865637574697665205370656c6c207c20486173683a20307830623064303036356462613331663931663635353261383730323239353964633830326530643930323430323939386366343731376262646434323437316162a264697066735822122015b31026e768b2fa8a2b2a91fee18e99e783c1cf7668b1360c4569df04f76d5b64736f6c634300060c0033" +} diff --git a/core/helpers/hardhat/erc20.ts b/core/helpers/hardhat/erc20.ts index 04c9dcd94..8d2d3a584 100644 --- a/core/helpers/hardhat/erc20.ts +++ b/core/helpers/hardhat/erc20.ts @@ -8,7 +8,6 @@ import { overwriteUintMappingInAddress, runBalanceSlotDiscoveryLoopForERC20Token export const determineBalanceSlot = async ( collateralType: CollateralType ): Promise<[string, 'vyper' | 'solidity'] | [null, null]> => { - console.info('Determining balance slot...'); const collateralConfig = getCollateralConfigByType(collateralType); const tokenContractAddress = await getContractAddressByName(TEST_NETWORK, collateralConfig.symbol); try { diff --git a/core/helpers/hardhat/overwrites.ts b/core/helpers/hardhat/overwrites.ts new file mode 100644 index 000000000..af47da0af --- /dev/null +++ b/core/helpers/hardhat/overwrites.ts @@ -0,0 +1,21 @@ +import BigNumber from '../../src/bignumber'; +import { ethers } from 'ethers'; +import { getCollateralConfigByType } from '../../src/constants/COLLATERALS'; +import { DAI_NUMBER_OF_DIGITS } from '../../src/constants/UNITS'; +import executeTransaction from '../../src/execute'; +import createStructCoder from '../../src/helpers/createStructCoder'; +import { getOracleAddressByCollateralType } from '../../src/oracles'; +import { overwriteUintValueInAddress } from './slotOverwrite'; + +export const overwriteCurrentOraclePrice = async (network: string, collateralType: string, amount: BigNumber) => { + const collateralConfig = getCollateralConfigByType(collateralType); + const oracleAddress = await getOracleAddressByCollateralType(network, collateralType); + const amoutInteger = amount.shiftedBy(DAI_NUMBER_OF_DIGITS).toFixed(); + const valueWithValidity = createStructCoder().encode(['uint128', 'uint128'], ['1', amoutInteger]); + await overwriteUintValueInAddress( + oracleAddress, + collateralConfig.oracle.currentPriceSlotAddress, + valueWithValidity + ); + await executeTransaction(network, 'MCD_SPOT', 'poke', [ethers.utils.formatBytes32String(collateralType)]); +}; diff --git a/core/helpers/hardhat/slotOverwrite.ts b/core/helpers/hardhat/slotOverwrite.ts index 339b50358..5b4a0995f 100644 --- a/core/helpers/hardhat/slotOverwrite.ts +++ b/core/helpers/hardhat/slotOverwrite.ts @@ -21,10 +21,10 @@ export const generateMappingSlotAddress = ( export const overwriteUintValueInAddress = async ( address: string, slotAddress: string, - newValue: BigNumber, + newValue: BigNumber | string, provider: EthereumProvider = hre.network.provider ) => { - const hexValue = formatToHex(newValue, 32); + const hexValue = typeof newValue === 'string' ? newValue : formatToHex(newValue, 32); const storageToWrite = [address, slotAddress, hexValue]; await provider.send('hardhat_setStorageAt', storageToWrite); }; diff --git a/core/simulations/config.ts b/core/simulations/config.ts index 3297c2ff3..1cad20343 100644 --- a/core/simulations/config.ts +++ b/core/simulations/config.ts @@ -1,10 +1,11 @@ +import { Simulation } from './types'; import debtAuctionSimulation from './configs/createDebtAuctionSimulation'; import surplusAuctionBlockchain from './configs/surplusAuctionSimulation'; import wstethAuctionSimulation from './configs/wstethAuctionSimulation'; import surplusAuctionSimulation from './configs/createSurplusAcutionSimulation'; import blockWithVaultsInAllStates from './configs/blocksWithVaultsInAllStates'; import vaultLiquidation from './configs/vaultLiquidation'; -import { Simulation } from './types'; +import onboardNewCollateral from './configs/onboardNewCollateral'; export const SIMULATIONS: Simulation[] = [ debtAuctionSimulation, @@ -13,4 +14,5 @@ export const SIMULATIONS: Simulation[] = [ wstethAuctionSimulation, blockWithVaultsInAllStates, vaultLiquidation, + onboardNewCollateral, ]; diff --git a/core/simulations/configs/onboardNewCollateral.ts b/core/simulations/configs/onboardNewCollateral.ts new file mode 100644 index 000000000..0764b68f4 --- /dev/null +++ b/core/simulations/configs/onboardNewCollateral.ts @@ -0,0 +1,76 @@ +import BigNumber from '../../src/bignumber'; +import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network'; +import { addDaiToBalance } from '../../helpers/hardhat/balance'; +import { Simulation } from '../types'; +import { getAllCollateralTypes } from '../../src/constants/COLLATERALS'; +import { collectStabilityFees, fetchVault, liquidateVault } from '../../src/vaults'; +import { TEST_NETWORK } from '../../helpers/constants'; +import createVaultWithCollateral, { + calculateMinCollateralAmountToOpenVault, +} from '../helpers/createVaultWithCollateral'; +import deploySpell, { getAllSpellNames } from '../helpers/deploySpell'; +import executeSpell from '../helpers/executeSpell'; +import { getCurrentOraclePriceByCollateralType } from '../../src/oracles'; +import { overwriteCurrentOraclePrice } from '../../helpers/hardhat/overwrites'; +import promptToSelectOneOption from '../helpers/promptToSelectOneOption'; + +const simulation: Simulation = { + title: 'Onboard new collateral', + steps: [ + { + title: 'Reset blockchain fork and add balances', + entry: async () => { + await resetNetworkAndSetupWallet(15791971); + await addDaiToBalance(); + }, + }, + { + title: 'Deploy the spell', + entry: async () => { + const spellName = await promptToSelectOneOption( + 'Select the spell you want to deploy', + getAllSpellNames() + ); + const spellAddress = await deploySpell(TEST_NETWORK, spellName); + return { + spellAddress, + }; + }, + }, + { + title: 'Execute the spell', + entry: async context => { + await executeSpell(context.spellAddress); + }, + }, + { + title: 'Create new auction', + entry: async () => { + const collateralType = await promptToSelectOneOption( + 'Select the collateral symbol to add to the VAT', + getAllCollateralTypes() + ); + // overwrite oracle price + await overwriteCurrentOraclePrice(TEST_NETWORK, collateralType, new BigNumber(1000)); + const oraclePrice = await getCurrentOraclePriceByCollateralType(TEST_NETWORK, collateralType); + console.info(`New ${collateralType} oracle price is ${oraclePrice.toFixed()} DAI`); + // create and liquidate vault + const collateralOwned = await calculateMinCollateralAmountToOpenVault(collateralType); + const vaultId = await createVaultWithCollateral(collateralType, collateralOwned); + await warpTime(60 * 24 * 30, 60); + await collectStabilityFees(TEST_NETWORK, collateralType); + const vault = await fetchVault(TEST_NETWORK, vaultId); + await liquidateVault(TEST_NETWORK, vault.collateralType, vault.address); + }, + }, + { + title: 'Skip time', + entry: async context => { + await warpTime(60, 60); + return context; + }, + }, + ], +}; + +export default simulation; diff --git a/core/simulations/configs/vaultLiquidation.ts b/core/simulations/configs/vaultLiquidation.ts index 95ccd4165..797d59012 100644 --- a/core/simulations/configs/vaultLiquidation.ts +++ b/core/simulations/configs/vaultLiquidation.ts @@ -1,53 +1,13 @@ import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network'; import { addDaiToBalance, addMkrToBalance } from '../../helpers/hardhat/balance'; import { Simulation } from '../types'; -import prompts from 'prompts'; -import COLLATERALS from '../../src/constants/COLLATERALS'; import { collectStabilityFees, fetchVault, liquidateVault } from '../../src/vaults'; import { TEST_NETWORK } from '../../helpers/constants'; import createVaultWithCollateral, { calculateMinCollateralAmountToOpenVault, + getLiquidatableCollateralTypes, } from '../helpers/createVaultWithCollateral'; - -const UNSUPPORTED_COLLATERAL_TYPES = [ - 'CRVV1ETHSTETH-A', // collateral handled differently - 'UNIV2DAIUSDC-A', // Liquidation limit too high (fails with "Dog/liquidation-limit-hit") - 'WSTETH-B', // does not accumulate stability fee rate at all. -]; - -export const getLiquidatableCollateralTypes = () => { - return Object.keys(COLLATERALS).filter(collateralType => !UNSUPPORTED_COLLATERAL_TYPES.includes(collateralType)); -}; - -const getCollateralType = async () => { - const { collateralType } = await prompts([ - { - type: 'select', - name: 'collateralType', - message: 'Select the collateral symbol to add to the VAT.', - choices: getLiquidatableCollateralTypes() - .sort() - .map(collateral => ({ - title: collateral, - value: collateral, - })), - }, - ]); - return collateralType; -}; - -const getBaseContext = async () => { - const collateralType = await getCollateralType(); - const decimals = COLLATERALS[collateralType].decimals; - const collateralOwned = await calculateMinCollateralAmountToOpenVault(collateralType); - - console.info(`Collateral in the VAT initially: ${collateralOwned.toFixed()}`); - return { - collateralType, - decimals, - collateralOwned, - }; -}; +import promptToSelectOneOption from '../helpers/promptToSelectOneOption'; const simulation: Simulation = { title: 'Simulate liquidation Auctions', @@ -56,13 +16,21 @@ const simulation: Simulation = { title: 'Reset blockchain fork', entry: async () => { await resetNetworkAndSetupWallet(); - return getBaseContext(); + const collateralType = await promptToSelectOneOption( + 'Select the collateral symbol to add to the VAT.', + getLiquidatableCollateralTypes() + ); + return { + collateralType, + }; }, }, { title: 'Create the vault', entry: async context => { - const latestVaultId = await createVaultWithCollateral(context.collateralType, context.collateralOwned); + const collateralOwned = await calculateMinCollateralAmountToOpenVault(context.collateralType); + console.info(`Minimum collateral amount to open vault: ${collateralOwned.toFixed()}`); + const latestVaultId = await createVaultWithCollateral(context.collateralType, collateralOwned); return { ...context, latestVaultId }; }, }, diff --git a/core/simulations/docker/Dockerfile b/core/simulations/docker/Dockerfile new file mode 100644 index 000000000..f0b16dfa8 --- /dev/null +++ b/core/simulations/docker/Dockerfile @@ -0,0 +1,3 @@ +FROM vulcanize/dapptools:v0.30.0-v1.10.16-statediff-3.0.2a + +ENTRYPOINT ["tail", "-f", "/dev/null"] diff --git a/core/simulations/docker/docker-compose.yaml b/core/simulations/docker/docker-compose.yaml new file mode 100644 index 000000000..ec4ea327b --- /dev/null +++ b/core/simulations/docker/docker-compose.yaml @@ -0,0 +1,21 @@ +version: '3' + +services: + + spells: + restart: "no" + build: + context: . + + core: + restart: "no" + ports: + - '8545:8545' + expose: + - 8545 + env_file: + - '../../.env' + build: + context: ../../../ + dockerfile: ./core/Dockerfile + target: hardhat diff --git a/core/simulations/helpers/createVaultWithCollateral.ts b/core/simulations/helpers/createVaultWithCollateral.ts index c346a8e19..8bd1491ae 100644 --- a/core/simulations/helpers/createVaultWithCollateral.ts +++ b/core/simulations/helpers/createVaultWithCollateral.ts @@ -1,6 +1,7 @@ +import { ethers } from 'ethers'; +import BigNumber from '../../src/bignumber'; import { setCollateralInVat } from '../../helpers/hardhat/balance'; import { getCollateralConfigByType } from '../../src/constants/COLLATERALS'; -import BigNumber from '../../src/bignumber'; import { changeVaultContents, fetchVault, openVault, fetchVaultCollateralParameters } from '../../src/vaults'; import { HARDHAT_PUBLIC_KEY, TEST_NETWORK } from '../../helpers/constants'; import { @@ -17,9 +18,20 @@ import { } from '../../src/wallet'; import { MAX } from '../../src/constants/UNITS'; import { CollateralConfig, CollateralType } from '../../src/types'; -import { ethers } from 'ethers'; import { roundDownToFirstSignificantDecimal, roundUpToFirstSignificantDecimal } from '../../helpers/hex'; import { determineBalanceSlot, setCollateralInWallet } from '../../helpers/hardhat/erc20'; +import { getAllCollateralTypes } from '../../src/constants/COLLATERALS'; + +const UNSUPPORTED_COLLATERAL_TYPES = [ + 'CRVV1ETHSTETH-A', // Collateral handled differently + 'UNIV2DAIUSDC-A', // Liquidation limit too high (fails with "Dog/liquidation-limit-hit") + 'WSTETH-B', // Does not accumulate stability fee rate at all + 'RETH-A', // [temporary] this collateral is not yet deployed, tested via different flow +]; + +export const getLiquidatableCollateralTypes = () => { + return getAllCollateralTypes().filter(collateralType => !UNSUPPORTED_COLLATERAL_TYPES.includes(collateralType)); +}; const setAndCheckCollateralInVat = async (collateralType: CollateralType, collateralOwned: BigNumber) => { console.info(`Setting ${collateralType} balance in VAT...`); diff --git a/core/simulations/helpers/deploySpell.ts b/core/simulations/helpers/deploySpell.ts new file mode 100644 index 000000000..5641ca226 --- /dev/null +++ b/core/simulations/helpers/deploySpell.ts @@ -0,0 +1,25 @@ +import { ethers } from 'ethers'; +import getSigner from '../../src/signer'; +import compiledSpells from '../../bytecode/compiledSpells.json'; + +export const getAllSpellNames = function (): string[] { + return Object.keys(compiledSpells).sort(); +}; + +const deploySpell = async function (network: string, name: string): Promise { + console.info(`Deploying spell "${name}"`); + + if (!(name in compiledSpells)) { + throw new Error(`spel "${name}" not found in compiled spells`); + } + const bytecode: string = (compiledSpells as Record)[name]; + + const signer = await getSigner(network); + const factory = new ethers.ContractFactory([], bytecode, signer); + const contract = await factory.deploy(); + await contract.deployTransaction.wait(); + console.info(`Spell has been deployed at ${contract.address}`); + return contract.address; +}; + +export default deploySpell; diff --git a/core/simulations/helpers/executeSpell.ts b/core/simulations/helpers/executeSpell.ts new file mode 100644 index 000000000..5d81ea19c --- /dev/null +++ b/core/simulations/helpers/executeSpell.ts @@ -0,0 +1,56 @@ +import BigNumber from '../../src/bignumber'; +import hre from 'hardhat'; +import { TEST_NETWORK } from '../../helpers/constants'; +import getContract from '../../src/contracts'; +import { MKR_NUMBER_OF_DIGITS } from '../../src/constants/UNITS'; +import { addMkrToBalance } from '../../helpers/hardhat/balance'; + +const ONE_WEEK_SECONDS = 60 * 60 * 24 * 7; + +const ethers = hre.ethers; +const provider = hre.network.provider; + +const getMaximumVotingPoverInMkr = async () => { + const chiefContract = await getContract(TEST_NETWORK, 'MCD_ADM'); + const hatAddress = await chiefContract.hat(); + const approvals = await chiefContract.approvals(hatAddress); + return new BigNumber(approvals._hex).shiftedBy(-MKR_NUMBER_OF_DIGITS); +}; + +const voteForSpell = async (spellAddress: string, mkrAmount: BigNumber) => { + const govContract = await getContract(TEST_NETWORK, 'MCD_GOV', true); + const chiefContract = await getContract(TEST_NETWORK, 'MCD_ADM', true); + const mkrAmountInteger = mkrAmount.shiftedBy(MKR_NUMBER_OF_DIGITS).toFixed(0); + await govContract['approve(address,uint256)'](chiefContract.address, mkrAmountInteger); + await chiefContract.lock(mkrAmountInteger); + await chiefContract.etch([spellAddress]); + const slate = ethers.utils.keccak256(ethers.utils.hexZeroPad(spellAddress, 32)); + await chiefContract['vote(bytes32)'](slate); + await chiefContract.lift(spellAddress); +}; + +const executeSpell = async function (spellAddress: string) { + console.info(`executing spell "${spellAddress}": minting enough MKR...`); + const maximumVotingPoverMkr = await getMaximumVotingPoverInMkr(); + await addMkrToBalance(maximumVotingPoverMkr.plus(1)); + + console.info(`executing spell "${spellAddress}": voting for the spell...`); + await voteForSpell(spellAddress, maximumVotingPoverMkr.plus(1)); + const spellAbi = ['function schedule() external', 'function cast() external']; + const spellContract = await ethers.getContractAt(spellAbi, spellAddress); + + console.info(`executing spell "${spellAddress}": scheduling spell...`); + await spellContract.schedule(); + + console.info(`executing spell "${spellAddress}": warping time...`); + const block = await ethers.provider.getBlock('latest'); + await provider.request({ + method: 'evm_setNextBlockTimestamp', + params: [block.timestamp + ONE_WEEK_SECONDS], + }); + + console.info(`executing spell "${spellAddress}": casting...`); + await spellContract.cast(); +}; + +export default executeSpell; diff --git a/core/simulations/helpers/promptToSelectOneOption.ts b/core/simulations/helpers/promptToSelectOneOption.ts new file mode 100644 index 000000000..4bf595aaa --- /dev/null +++ b/core/simulations/helpers/promptToSelectOneOption.ts @@ -0,0 +1,21 @@ +import prompts from 'prompts'; + +const promptToSelectOneOption = async (title: string, values: string[]) => { + if (values.length <= 1) { + return values[0]; + } + const { selectedValue } = await prompts([ + { + type: 'select', + name: 'selectedValue', + message: title, + choices: values.map(value => ({ + title: value, + value: value, + })), + }, + ]); + return selectedValue; +}; + +export default promptToSelectOneOption; diff --git a/core/src/abis/MCD_ADM.json b/core/src/abis/MCD_ADM.json new file mode 100644 index 000000000..e750d6f49 --- /dev/null +++ b/core/src/abis/MCD_ADM.json @@ -0,0 +1,713 @@ +[ + { + "inputs": [ + { + "internalType": "contract DSToken", + "name": "GOV", + "type": "address" + }, + { + "internalType": "contract DSToken", + "name": "IOU", + "type": "address" + }, + { + "internalType": "uint256", + "name": "MAX_YAYS", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "slate", + "type": "bytes32" + } + ], + "name": "Etch", + "type": "event" + }, + { + "anonymous": true, + "inputs": [ + { + "indexed": true, + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "foo", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "bar", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "fax", + "type": "bytes" + } + ], + "name": "LogNote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authority", + "type": "address" + } + ], + "name": "LogSetAuthority", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "LogSetOwner", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "GOV", + "outputs": [ + { + "internalType": "contract DSToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "IOU", + "outputs": [ + { + "internalType": "contract DSToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_YAYS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "authority", + "outputs": [ + { + "internalType": "contract DSAuthority", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "code", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + } + ], + "name": "canCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address[]", + "name": "yays", + "type": "address[]" + } + ], + "name": "etch", + "outputs": [ + { + "internalType": "bytes32", + "name": "slate", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "free", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "code", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + } + ], + "name": "getCapabilityRoles", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "getUserRoles", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + }, + { + "internalType": "uint8", + "name": "role", + "type": "uint8" + } + ], + "name": "hasUserRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "hat", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "code", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + } + ], + "name": "isCapabilityPublic", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "isUserRoot", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "last", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "launch", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "whom", + "type": "address" + } + ], + "name": "lift", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "live", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "lock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract DSAuthority", + "name": "authority_", + "type": "address" + } + ], + "name": "setAuthority", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "name": "setOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "code", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setPublicCapability", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint8", + "name": "role", + "type": "uint8" + }, + { + "internalType": "address", + "name": "code", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setRoleCapability", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setRootUser", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + }, + { + "internalType": "uint8", + "name": "role", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setUserRole", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "slates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes32", + "name": "slate", + "type": "bytes32" + } + ], + "name": "vote", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address[]", + "name": "yays", + "type": "address[]" + } + ], + "name": "vote", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "votes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/core/src/auctions.ts b/core/src/auctions.ts index 01743c152..3a3b13ce4 100644 --- a/core/src/auctions.ts +++ b/core/src/auctions.ts @@ -88,9 +88,10 @@ const enrichAuctionWithMarketValues = async function (auction: Auction, network: ...auctionWithMarketValues, transactionGrossProfit, }; - } catch (error) { + } catch (error: any) { // since it's expected that some collaterals are not tradable on some networks // we should just ignore this error + console.warn(`auction ${auction.id} is not tradable`, error?.message); return auction; } }; diff --git a/core/src/calleeFunctions/CurveLpTokenUniv3Callee.ts b/core/src/calleeFunctions/CurveLpTokenUniv3Callee.ts index 1f8b86e7e..2aa220ead 100644 --- a/core/src/calleeFunctions/CurveLpTokenUniv3Callee.ts +++ b/core/src/calleeFunctions/CurveLpTokenUniv3Callee.ts @@ -45,9 +45,9 @@ const getMarketPrice = async function ( return daiAmount.dividedBy(collateralAmount); }; -const UniswapV2CalleeDai: CalleeFunctions = { +const CurveLpTokenUniv3Callee: CalleeFunctions = { getCalleeData, getMarketPrice, }; -export default UniswapV2CalleeDai; +export default CurveLpTokenUniv3Callee; diff --git a/core/src/calleeFunctions/WstETHCurveUniv3Callee.ts b/core/src/calleeFunctions/WstETHCurveUniv3Callee.ts index 76c115137..e082298a9 100644 --- a/core/src/calleeFunctions/WstETHCurveUniv3Callee.ts +++ b/core/src/calleeFunctions/WstETHCurveUniv3Callee.ts @@ -1,10 +1,10 @@ import type { CalleeFunctions, CollateralConfig } from '../types'; import { ethers } from 'ethers'; import BigNumber from '../bignumber'; -import getContract, { getContractAddressByName, getJoinNameByCollateralType } from '../contracts'; -import { ETH_NUMBER_OF_DIGITS } from '../constants/UNITS'; +import { getContractAddressByName, getJoinNameByCollateralType } from '../contracts'; import { convertStethToEth } from './helpers/curve'; import { convertCollateralToDai, UNISWAP_FEE } from './helpers/uniswapV3'; +import { convertWstethToSteth } from './helpers/wsteth'; const getCalleeData = async function ( network: string, @@ -28,11 +28,11 @@ const getMarketPrice = async function ( collateral: CollateralConfig, collateralAmount: BigNumber ): Promise { + if (collateral.exchange.callee !== 'WstETHCurveUniv3Callee') { + throw new Error(`Invalid callee used to get market price for ${collateral.ilk}`); + } // convert wstETH into stETH - const collateralContract = await getContract(network, collateral.symbol); - const collateralIntegerAmount = collateralAmount.shiftedBy(collateral.decimals).toFixed(0); - const stethIntegerAmount = await collateralContract.getStETHByWstETH(collateralIntegerAmount); - const stethAmount = new BigNumber(stethIntegerAmount._hex).shiftedBy(-ETH_NUMBER_OF_DIGITS); + const stethAmount = await convertWstethToSteth(network, collateralAmount); // convert stETH into ETH const ethAmount = await convertStethToEth(network, stethAmount); diff --git a/core/src/calleeFunctions/helpers/rocket.ts b/core/src/calleeFunctions/helpers/rocket.ts new file mode 100644 index 000000000..161acbb35 --- /dev/null +++ b/core/src/calleeFunctions/helpers/rocket.ts @@ -0,0 +1,26 @@ +import { ethers } from 'ethers'; +import BigNumber from '../../bignumber'; +import getProvider from '../../provider'; +import CURVE_POOL_ABI from '../../abis/CURVE_POOL.json'; +import { ETH_NUMBER_OF_DIGITS } from '../../constants/UNITS'; + +export const ROCKET_POOL_ADDRESS = '0x447Ddd4960d9fdBF6af9a790560d0AF76795CB08'; +export const ROCKET_POOL_RETH_INDEX = 0; + +const getRocketPoolContract = async function (network: string): Promise { + const provider = await getProvider(network); + return new ethers.Contract(ROCKET_POOL_ADDRESS, CURVE_POOL_ABI as ethers.ContractInterface, provider); +}; + +export const convertRethToWsteth = async function (network: string, rethAmount: BigNumber) { + const curvePoolContract = await getRocketPoolContract(network); + const rethIntegerAmount = rethAmount.shiftedBy(ETH_NUMBER_OF_DIGITS).toFixed(0); + const wstethIntegerAmount = await curvePoolContract.calc_withdraw_one_coin( + rethIntegerAmount, + ROCKET_POOL_RETH_INDEX, + { + gasLimit: 1000000, + } + ); + return new BigNumber(wstethIntegerAmount._hex).shiftedBy(-ETH_NUMBER_OF_DIGITS); +}; diff --git a/core/src/calleeFunctions/helpers/wsteth.ts b/core/src/calleeFunctions/helpers/wsteth.ts new file mode 100644 index 000000000..319e6ae08 --- /dev/null +++ b/core/src/calleeFunctions/helpers/wsteth.ts @@ -0,0 +1,12 @@ +import BigNumber from '../../bignumber'; +import { getCollateralConfigBySymbol } from '../../constants/COLLATERALS'; +import { ETH_NUMBER_OF_DIGITS } from '../../constants/UNITS'; +import getContract from '../../contracts'; + +export const convertWstethToSteth = async function (network: string, collateralAmount: BigNumber) { + const collateralConfig = getCollateralConfigBySymbol('WSTETH'); + const collateralContract = await getContract(network, collateralConfig.symbol); + const collateralIntegerAmount = collateralAmount.shiftedBy(collateralConfig.decimals).toFixed(0); + const stethIntegerAmount = await collateralContract.getStETHByWstETH(collateralIntegerAmount); + return new BigNumber(stethIntegerAmount._hex).shiftedBy(-ETH_NUMBER_OF_DIGITS); +}; diff --git a/core/src/calleeFunctions/index.ts b/core/src/calleeFunctions/index.ts index c2d98f77a..412a0ae78 100644 --- a/core/src/calleeFunctions/index.ts +++ b/core/src/calleeFunctions/index.ts @@ -6,6 +6,7 @@ import UniswapV2LpTokenCalleeDai from './UniswapV2LpTokenCalleeDai'; import WstETHCurveUniv3Callee from './WstETHCurveUniv3Callee'; import CurveLpTokenUniv3Callee from './CurveLpTokenUniv3Callee'; import UniswapV3Callee from './UniswapV3Callee'; +import rETHCurveUniv3Callee from './rETHCurveUniv3Callee'; import { getCollateralConfigByType, getCollateralConfigBySymbol } from '../constants/COLLATERALS'; const MARKET_PRICE_CACHE_MS = 10 * 1000; @@ -16,6 +17,7 @@ const allCalleeFunctions: Record = { WstETHCurveUniv3Callee, CurveLpTokenUniv3Callee, UniswapV3Callee, + rETHCurveUniv3Callee, }; export const getCalleeData = async function ( diff --git a/core/src/calleeFunctions/rETHCurveUniv3Callee.ts b/core/src/calleeFunctions/rETHCurveUniv3Callee.ts new file mode 100644 index 000000000..9cbed0c91 --- /dev/null +++ b/core/src/calleeFunctions/rETHCurveUniv3Callee.ts @@ -0,0 +1,58 @@ +import { ethers } from 'ethers'; +import type { CalleeFunctions, CollateralConfig } from '../types'; +import BigNumber from '../bignumber'; +import { getContractAddressByName, getJoinNameByCollateralType } from '../contracts'; +import { encodeRoute, convertCollateralToDai } from './helpers/uniswapV3'; +import { convertStethToEth } from './helpers/curve'; +import { convertRethToWsteth } from './helpers/rocket'; +import { convertWstethToSteth } from './helpers/wsteth'; +import { NULL_ADDRESS } from '../constants/UNITS'; + +const getCalleeData = async function ( + network: string, + collateral: CollateralConfig, + profitAddress: string +): Promise { + if (collateral.exchange.callee !== 'rETHCurveUniv3Callee') { + throw new Error(`Can not encode route for the "${collateral.ilk}"`); + } + const route = await encodeRoute(network, collateral.exchange.route); + const joinAdapterAddress = await getContractAddressByName(network, getJoinNameByCollateralType(collateral.ilk)); + const minProfit = 1; + const typesArray = ['address', 'address', 'uint256', 'bytes', 'address']; + return ethers.utils.defaultAbiCoder.encode(typesArray, [ + profitAddress, + joinAdapterAddress, + minProfit, + route, + NULL_ADDRESS, + ]); +}; + +const getMarketPrice = async function ( + network: string, + _collateral: CollateralConfig, + collateralAmount: BigNumber +): Promise { + // convert rETH into wstETH + const wstethAmount = await convertRethToWsteth(network, collateralAmount); + + // convert wstETH into stETH (unwrap) + const stethAmount = await convertWstethToSteth(network, wstethAmount); + + // convert stETH into ETH + const ethAmount = await convertStethToEth(network, stethAmount); + + // convert ETH into DAI + const daiAmount = await convertCollateralToDai(network, 'ETH', ethAmount); + + // return price per unit + return daiAmount.dividedBy(collateralAmount); +}; + +const rETHCurveUniv3Callee: CalleeFunctions = { + getCalleeData, + getMarketPrice, +}; + +export default rETHCurveUniv3Callee; diff --git a/core/src/constants/CALLEES.ts b/core/src/constants/CALLEES.ts index cea460530..e845ee9bf 100644 --- a/core/src/constants/CALLEES.ts +++ b/core/src/constants/CALLEES.ts @@ -9,6 +9,7 @@ const CALLEES: Record = { WstETHCurveUniv3Callee: '0xC2D837173592194131827775a6Cd88322a98C825', CurveLpTokenUniv3Callee: '0x71f2198849F3B1372EA90c079BD634928583f2d2', UniswapV3Callee: '0xdB9C76109d102d2A1E645dCa3a7E671EBfd8e11A', + rETHCurveUniv3Callee: '0x7cdAb0fE16efb1EFE89e53B141347D7F299d6610', }, '0x5': { UniswapV2CalleeDai: '0x6d9139ac89ad2263f138633de20e47bcae253938', diff --git a/core/src/constants/COLLATERALS.ts b/core/src/constants/COLLATERALS.ts index 08009b86f..12fd8dc31 100644 --- a/core/src/constants/COLLATERALS.ts +++ b/core/src/constants/COLLATERALS.ts @@ -446,6 +446,17 @@ const COLLATERALS: Record = { }, oracle: CONFIG_WITH_NEXT_PRICE, }, + 'RETH-A': { + title: 'Rocket Pool ETH', + ilk: 'RETH-A', + symbol: 'RETH', + decimals: 18, + exchange: { + callee: 'rETHCurveUniv3Callee', + route: ['ETH'], + }, + oracle: CONFIG_WITH_NEXT_PRICE, + }, }; export const getCollateralConfigBySymbol = function (symbol: string): CollateralConfig { @@ -466,11 +477,11 @@ export const getCollateralConfigByType = function (collateralType: string): Coll export const getAllCollateralSymbols = function (): string[] { const collateralSymbols = Object.values(COLLATERALS).map(collateral => collateral.symbol); - return Array.from(new Set(collateralSymbols)); + return Array.from(new Set(collateralSymbols)).sort(); }; export const getAllCollateralTypes = function (): string[] { - return Object.keys(COLLATERALS); + return Object.keys(COLLATERALS).sort(); }; export default COLLATERALS; diff --git a/core/src/constants/UNITS.ts b/core/src/constants/UNITS.ts index a36f300b0..bd8bbe159 100644 --- a/core/src/constants/UNITS.ts +++ b/core/src/constants/UNITS.ts @@ -1,6 +1,7 @@ import BigNumber from 'bignumber.js'; export const NULL_BYTES = '0x'; +export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; // Common Maker Units https://github.com/makerdao/dss/blob/master/DEVELOPING.md#units // WAD: fixed point decimal with 18 decimals (for basic quantities, e.g. balances) diff --git a/core/src/contracts.ts b/core/src/contracts.ts index c50b99ce1..7c6d49bef 100644 --- a/core/src/contracts.ts +++ b/core/src/contracts.ts @@ -27,6 +27,7 @@ import MEDIAN_PRICE_FEED from './abis/MEDIAN_PRICE_FEED.json'; import MCD_SPOT from './abis/MCD_SPOT.json'; import MCD_JUG from './abis/MCD_JUG.json'; import ERC20 from './abis/ERC20.json'; +import MCD_ADM from './abis/MCD_ADM.json'; import getSigner from './signer'; import memoizee from 'memoizee'; @@ -65,6 +66,7 @@ export const getContractInterfaceByName = async function (contractName: string): MCD_JUG, CDP_REGISTRY, MCD_CROPPER, + MCD_ADM, }; if (Object.keys(ABIs).includes(contractName)) { return ABIs[contractName]; diff --git a/core/src/helpers/createStructCoder.ts b/core/src/helpers/createStructCoder.ts new file mode 100644 index 000000000..a660e041b --- /dev/null +++ b/core/src/helpers/createStructCoder.ts @@ -0,0 +1,9 @@ +import { ethers } from 'ethers'; + +const createStructCoder = function (length = 16) { + const coder = new ethers.utils.AbiCoder(); + coder._getWordSize = () => length; + return coder; +}; + +export default createStructCoder; diff --git a/core/src/oracles.ts b/core/src/oracles.ts index ac09c8ed6..47cc79941 100644 --- a/core/src/oracles.ts +++ b/core/src/oracles.ts @@ -1,4 +1,4 @@ -import { getContractInterfaceByName } from './contracts'; +import { getContractAddressByName, getContractInterfaceByName } from './contracts'; import getProvider from './provider'; import { CollateralConfig, @@ -16,6 +16,11 @@ import { getCollateralConfigByType } from './constants/COLLATERALS'; const CACHE_EXPIRY_MS = 60 * 1000; +export const getOracleAddressByCollateralType = async function (network: string, collateralType: string) { + const collateralConfig = getCollateralConfigByType(collateralType); + return await getContractAddressByName(network, `PIP_${collateralConfig.symbol}`); +}; + const getOraclePriceSameSlotValidity = async ( slot: string, slotPriceValueBeginsAtPosition: number, @@ -95,7 +100,7 @@ const currentPriceExtractors: Record { describe('Sound values are extracted', () => { before(async () => { await setupRpcUrlAndGetNetworks(LOCAL_RPC_URL); - }); - beforeEach(async () => { await resetNetwork(15533000); }); - it('can reach all the oracles', async () => { - const expectedReturn: Record< - CollateralType, - { nextUnitPrice: string; currentUnitPrice: string; nextPriceChange: Date } - > = { - 'AAVE-A': { - nextUnitPrice: '150.79237464128204', - currentUnitPrice: '150.79237464128204', - nextPriceChange: new Date('2022-01-23T22:00:00.000Z'), - }, - 'BAL-A': { - currentUnitPrice: '11.80800329930906', - nextUnitPrice: '11.721140147069267', - nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), - }, - 'BAT-A': { - nextUnitPrice: '0.73', - currentUnitPrice: '0.71910538308', - nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), - }, - 'COMP-A': { - nextUnitPrice: '124.5640565401381', - currentUnitPrice: '124.5640565401381', - nextPriceChange: new Date('2022-01-23T22:00:00.000Z'), - }, - 'ETH-A': { - nextUnitPrice: '1712.2106886', - currentUnitPrice: '1712.2106886', - nextPriceChange: new Date('2022-09-09T10:00:00.000Z'), - }, - 'ETH-B': { - nextUnitPrice: '1602.1803800999999', - currentUnitPrice: '1602.1803800999999', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'ETH-C': { - nextUnitPrice: '1208.0159951', - currentUnitPrice: '1227.067888375', - nextPriceChange: new Date('2022-06-13T11:00:00.000Z'), - }, - 'GUSD-A': { - nextUnitPrice: 'NaN', - currentUnitPrice: '1', - nextPriceChange: new Date(NaN), - }, - 'KNC-A': { - nextUnitPrice: '1.5108', - currentUnitPrice: '1.4869', - nextPriceChange: new Date('2021-10-28T05:00:00.000Z'), - }, - 'LINK-A': { - nextUnitPrice: '7.2245', - currentUnitPrice: '7.159627035', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'LRC-A': { - nextUnitPrice: '0.8117493344000001', - currentUnitPrice: '0.7270649846852948', - nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), - }, - 'MANA-A': { - nextUnitPrice: '0.73075', - currentUnitPrice: '0.73075', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'PAXUSD-A': { - nextUnitPrice: 'NaN', - currentUnitPrice: '1', - nextPriceChange: new Date(NaN), - }, - 'RENBTC-A': { - nextUnitPrice: '20388.465', - currentUnitPrice: '20388.465', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'TUSD-A': { - nextUnitPrice: 'NaN', - currentUnitPrice: '1', - nextPriceChange: new Date(NaN), - }, - 'UNI-A': { - nextUnitPrice: '6.1622020819', - currentUnitPrice: '5.103855836', - nextPriceChange: new Date('2022-07-11T16:00:00.000Z'), - }, - 'USDC-A': { - nextUnitPrice: 'NaN', - currentUnitPrice: '1', - nextPriceChange: new Date(NaN), - }, - 'USDC-B': { - nextUnitPrice: 'NaN', - currentUnitPrice: '1', - nextPriceChange: new Date(NaN), - }, - 'USDT-A': { - nextUnitPrice: '1.0007712772150232', - currentUnitPrice: '1.0007712772150232', - nextPriceChange: new Date('2021-10-28T05:00:00.000Z'), - }, - 'WBTC-A': { - nextUnitPrice: '20388.465', - currentUnitPrice: '20388.465', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'WBTC-B': { - nextUnitPrice: '20388.465', - currentUnitPrice: '20388.465', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'WBTC-C': { - nextUnitPrice: '20388.465', - currentUnitPrice: '20388.465', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'YFI-A': { - nextUnitPrice: '9150', - currentUnitPrice: '9185.8368', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'ZRX-A': { - nextUnitPrice: '0.54008', - currentUnitPrice: '0.50224', - nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), - }, - 'MATIC-A': { - nextUnitPrice: '0.859281', - currentUnitPrice: '0.859281', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'WSTETH-A': { - nextUnitPrice: '1687.84305547955', - currentUnitPrice: '1687.84305547955', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'WSTETH-B': { - nextUnitPrice: '1687.84305547955', - currentUnitPrice: '1687.84305547955', - nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), - }, - 'CRVV1ETHSTETH-A': { - nextUnitPrice: '1633.547452878850724671', - currentUnitPrice: '1645.994835125363651071', - nextPriceChange: new Date('2022-09-14T12:01:47.000Z'), - }, - 'UNIV2DAIETH-A': { - nextUnitPrice: '111.536694644490420563', - currentUnitPrice: '115.716445113160358543', - nextPriceChange: new Date('2022-07-13T17:00:03.000Z'), - }, - 'UNIV2USDCETH-A': { - nextUnitPrice: '164916785.176105260363204747', - currentUnitPrice: '165534555.801045344024651968', - nextPriceChange: new Date('2022-09-14T12:01:47.000Z'), - }, - 'UNIV2ETHUSDT-A': { - nextUnitPrice: '228116379.650719357480121186', - currentUnitPrice: '230190196.687438171219371005', - nextPriceChange: new Date('2021-10-28T04:01:15.000Z'), - }, - 'UNIV2WBTCDAI-A': { - nextUnitPrice: '31892330.725591269457933196', - currentUnitPrice: '32196608.076982062517168305', - nextPriceChange: new Date('2022-07-11T16:09:40.000Z'), - }, - 'UNIV2WBTCETH-A': { - nextUnitPrice: '1102874511.239936578199968093', - currentUnitPrice: '1175008223.21111667836061111', - nextPriceChange: new Date('2022-07-13T17:00:03.000Z'), - }, - 'UNIV2LINKETH-A': { - nextUnitPrice: '567.672642511519510798', - currentUnitPrice: '566.984073123537837073', - nextPriceChange: new Date('2022-01-23T19:01:00.000Z'), - }, - 'UNIV2UNIETH-A': { - nextUnitPrice: '368.441439820843276851', - currentUnitPrice: '327.117645258478197955', - nextPriceChange: new Date('2022-07-11T16:09:40.000Z'), - }, - 'UNIV2AAVEETH-A': { - nextUnitPrice: '2503.767176345875098159', - currentUnitPrice: '2529.450702467409881126', - nextPriceChange: new Date('2021-11-22T23:04:46.000Z'), - }, - 'UNIV2DAIUSDT-A': { - nextUnitPrice: '2274141.032812901837192665', - currentUnitPrice: '2274109.765292120125373109', - nextPriceChange: new Date('2021-10-28T04:01:15.000Z'), - }, - 'UNIV2DAIUSDC-A': { - nextUnitPrice: '2252657.773463853818331742', - currentUnitPrice: '2252657.773463853818331742', - nextPriceChange: new Date('2022-09-14T12:01:47.000Z'), - }, - }; - for (const type of Object.keys(COLLATERALS)) { + const expectedReturn: Record< + CollateralType, + { nextUnitPrice: string; currentUnitPrice: string; nextPriceChange: Date } + > = { + 'AAVE-A': { + nextUnitPrice: '150.79237464128204', + currentUnitPrice: '150.79237464128204', + nextPriceChange: new Date('2022-01-23T22:00:00.000Z'), + }, + 'BAL-A': { + currentUnitPrice: '11.80800329930906', + nextUnitPrice: '11.721140147069267', + nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), + }, + 'BAT-A': { + nextUnitPrice: '0.73', + currentUnitPrice: '0.71910538308', + nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), + }, + 'COMP-A': { + nextUnitPrice: '124.5640565401381', + currentUnitPrice: '124.5640565401381', + nextPriceChange: new Date('2022-01-23T22:00:00.000Z'), + }, + 'ETH-A': { + nextUnitPrice: '1712.2106886', + currentUnitPrice: '1712.2106886', + nextPriceChange: new Date('2022-09-09T10:00:00.000Z'), + }, + 'ETH-B': { + nextUnitPrice: '1602.1803800999999', + currentUnitPrice: '1602.1803800999999', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'ETH-C': { + nextUnitPrice: '1208.0159951', + currentUnitPrice: '1227.067888375', + nextPriceChange: new Date('2022-06-13T11:00:00.000Z'), + }, + 'GUSD-A': { + nextUnitPrice: 'NaN', + currentUnitPrice: '1', + nextPriceChange: new Date(NaN), + }, + 'KNC-A': { + nextUnitPrice: '1.5108', + currentUnitPrice: '1.4869', + nextPriceChange: new Date('2021-10-28T05:00:00.000Z'), + }, + 'LINK-A': { + nextUnitPrice: '7.2245', + currentUnitPrice: '7.159627035', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'LRC-A': { + nextUnitPrice: '0.8117493344000001', + currentUnitPrice: '0.7270649846852948', + nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), + }, + 'MANA-A': { + nextUnitPrice: '0.73075', + currentUnitPrice: '0.73075', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'PAXUSD-A': { + nextUnitPrice: 'NaN', + currentUnitPrice: '1', + nextPriceChange: new Date(NaN), + }, + 'RENBTC-A': { + nextUnitPrice: '20388.465', + currentUnitPrice: '20388.465', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'TUSD-A': { + nextUnitPrice: 'NaN', + currentUnitPrice: '1', + nextPriceChange: new Date(NaN), + }, + 'UNI-A': { + nextUnitPrice: '6.1622020819', + currentUnitPrice: '5.103855836', + nextPriceChange: new Date('2022-07-11T16:00:00.000Z'), + }, + 'USDC-A': { + nextUnitPrice: 'NaN', + currentUnitPrice: '1', + nextPriceChange: new Date(NaN), + }, + 'USDC-B': { + nextUnitPrice: 'NaN', + currentUnitPrice: '1', + nextPriceChange: new Date(NaN), + }, + 'USDT-A': { + nextUnitPrice: '1.0007712772150232', + currentUnitPrice: '1.0007712772150232', + nextPriceChange: new Date('2021-10-28T05:00:00.000Z'), + }, + 'WBTC-A': { + nextUnitPrice: '20388.465', + currentUnitPrice: '20388.465', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'WBTC-B': { + nextUnitPrice: '20388.465', + currentUnitPrice: '20388.465', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'WBTC-C': { + nextUnitPrice: '20388.465', + currentUnitPrice: '20388.465', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'YFI-A': { + nextUnitPrice: '9150', + currentUnitPrice: '9185.8368', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'ZRX-A': { + nextUnitPrice: '0.54008', + currentUnitPrice: '0.50224', + nextPriceChange: new Date('2022-01-23T19:00:00.000Z'), + }, + 'MATIC-A': { + nextUnitPrice: '0.859281', + currentUnitPrice: '0.859281', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'WSTETH-A': { + nextUnitPrice: '1687.84305547955', + currentUnitPrice: '1687.84305547955', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'WSTETH-B': { + nextUnitPrice: '1687.84305547955', + currentUnitPrice: '1687.84305547955', + nextPriceChange: new Date('2022-09-14T13:00:00.000Z'), + }, + 'CRVV1ETHSTETH-A': { + nextUnitPrice: '1633.547452878850724671', + currentUnitPrice: '1645.994835125363651071', + nextPriceChange: new Date('2022-09-14T12:01:47.000Z'), + }, + 'UNIV2DAIETH-A': { + nextUnitPrice: '111.536694644490420563', + currentUnitPrice: '115.716445113160358543', + nextPriceChange: new Date('2022-07-13T17:00:03.000Z'), + }, + 'UNIV2USDCETH-A': { + nextUnitPrice: '164916785.176105260363204747', + currentUnitPrice: '165534555.801045344024651968', + nextPriceChange: new Date('2022-09-14T12:01:47.000Z'), + }, + 'UNIV2ETHUSDT-A': { + nextUnitPrice: '228116379.650719357480121186', + currentUnitPrice: '230190196.687438171219371005', + nextPriceChange: new Date('2021-10-28T04:01:15.000Z'), + }, + 'UNIV2WBTCDAI-A': { + nextUnitPrice: '31892330.725591269457933196', + currentUnitPrice: '32196608.076982062517168305', + nextPriceChange: new Date('2022-07-11T16:09:40.000Z'), + }, + 'UNIV2WBTCETH-A': { + nextUnitPrice: '1102874511.239936578199968093', + currentUnitPrice: '1175008223.21111667836061111', + nextPriceChange: new Date('2022-07-13T17:00:03.000Z'), + }, + 'UNIV2LINKETH-A': { + nextUnitPrice: '567.672642511519510798', + currentUnitPrice: '566.984073123537837073', + nextPriceChange: new Date('2022-01-23T19:01:00.000Z'), + }, + 'UNIV2UNIETH-A': { + nextUnitPrice: '368.441439820843276851', + currentUnitPrice: '327.117645258478197955', + nextPriceChange: new Date('2022-07-11T16:09:40.000Z'), + }, + 'UNIV2AAVEETH-A': { + nextUnitPrice: '2503.767176345875098159', + currentUnitPrice: '2529.450702467409881126', + nextPriceChange: new Date('2021-11-22T23:04:46.000Z'), + }, + 'UNIV2DAIUSDT-A': { + nextUnitPrice: '2274141.032812901837192665', + currentUnitPrice: '2274109.765292120125373109', + nextPriceChange: new Date('2021-10-28T04:01:15.000Z'), + }, + 'UNIV2DAIUSDC-A': { + nextUnitPrice: '2252657.773463853818331742', + currentUnitPrice: '2252657.773463853818331742', + nextPriceChange: new Date('2022-09-14T12:01:47.000Z'), + }, + }; + for (const type of getLiquidatableCollateralTypes()) { + it(`can reach ${type} oracle`, async () => { const liquidationRatioAndAddress = await fetchLiquidationRatioAndOracleAddress(TEST_NETWORK, type); - expect(liquidationRatioAndAddress.oracleAddress).not.to.eq('0x0000000000000000000000000000000000000000'); + expect(liquidationRatioAndAddress.oracleAddress).not.to.eq(NULL_ADDRESS); const prices = await getOsmPrices(TEST_NETWORK, liquidationRatioAndAddress.oracleAddress, type); expect(expectedReturn[type].currentUnitPrice).to.eq(prices.currentUnitPrice.toFixed()); if (expectedReturn[type].nextPriceChange.getTime()) { @@ -416,9 +413,10 @@ describe('Sound values are extracted', () => { expect(prices.nextPriceChange.getTime()).to.be.NaN; } expect(expectedReturn[type].nextUnitPrice).to.eq(prices.nextUnitPrice.toFixed()); - } - }); + }); + } }); + describe(`Collateral vault simulation liquidation `, () => { before(async () => { await createWalletForRpc(); @@ -426,7 +424,7 @@ describe(`Collateral vault simulation liquidation `, () => { // set max global liquidation limit - `Hole` of dog.sol contract await overwriteUintValue('MCD_DOG', '0x4', MAX); }); - getLiquidatableCollateralTypes().forEach(collateralType => { + for (const collateralType of getLiquidatableCollateralTypes()) { it(`runs the simulaton for ${collateralType}`, async () => { let collateralOwned: BigNumber; try { @@ -460,5 +458,5 @@ describe(`Collateral vault simulation liquidation `, () => { await liquidateVault(TEST_NETWORK, vault.collateralType, vault.address); }); - }); + } }); diff --git a/core/tsconfig.json b/core/tsconfig.json index e5cc4e50f..a9198b052 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -36,7 +36,8 @@ "./test/**/*.json", "./simulations/**/*.ts", "./simulations/**/*.json", - "./helpers/**/*.ts" + "./helpers/**/*.ts", + "./bytecode/**/*.json" ], "exclude": [ "node_modules" diff --git a/frontend/components/auction/collateral/CollateralAuctionExecutionBlock.vue b/frontend/components/auction/collateral/CollateralAuctionExecutionBlock.vue index 766b9315c..b28f9ff5f 100644 --- a/frontend/components/auction/collateral/CollateralAuctionExecutionBlock.vue +++ b/frontend/components/auction/collateral/CollateralAuctionExecutionBlock.vue @@ -9,7 +9,7 @@ :fees="fees" show-different-wallet-info /> -
+