-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: RWA Offboarding Checklist #42
base: master
Are you sure you want to change the base?
Changes from all commits
18ea200
1069a8a
4c1dd49
be58441
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
# RWA Checklists | ||
|
||
## RWA Onboarding Checklist | ||
|
||
* [ ] Deployed Contracts | ||
* [ ] `RwaToken` (Token Used as Collateral In Adapter) | ||
* [ ] deployed via [`RwaTokenFactory`](https://github.com/makerdao/rwa-toolkit/blob/master/src/tokens/RwaTokenFactory.sol) | ||
* [ ] Fab matches [chainlog](https://chainlog.makerdao.com/) | ||
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/blob/92c79aac24ef7645902ce4be57ba41b19e6c7dd5/src/tokens/RwaToken.sol) and it's consistent with previous RWA onboarding | ||
* [ ] Rwa Token transferred to MCD Pause Proxy | ||
* [ ] `createRwaToken` parameters are correct | ||
* [ ] `name` is in `RWA-XYZ` format | ||
* [ ] `symbol` is in `RWAXYZ` format | ||
* [ ] `recipient` matches MCD Pause Proxy | ||
* [ ] `AuthGemJoin` (Join Adapter) | ||
* [ ] deployed via [JoinFab](https://github.com/makerdao/JoinFab/blob/master/src/JoinFab.sol) | ||
* [ ] Fab matches [chainlog](https://chainlog.makerdao.com/) | ||
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/dss-gem-joins/blob/8ca0a7fdd5edc6ed3da68c3ffdfadfb9540c83f7/src/join-auth.sol) and it's consistent with previous RWA onboarding (NOTE: Etherscan may have a bug where it displays additional code for `AuthGemJoin`. In this case, using `cast interface` or otherwise, ensure that this code cannot be executed) | ||
* [ ] `newAuthGemJoin` parameters are correct | ||
* [ ] `owner` matches `PAUSE_PROXY` | ||
* [ ] `ilk` is the `bytes32` representation of "RWAXYZ-A" | ||
* [ ] `cast --to-ascii <bytes32>` matches ASCII Ilk | ||
* [ ] `cast --to-bytes32 $(cast --from-ascii "RWAXYZ-A")` matches `bytes32` (to check the amount of padding zeroes is correct) | ||
* [ ] `gem` matches `RwaToken` deployed contract | ||
* [ ] check `wards` | ||
* [ ] `MCD_PAUSE_PROXY` is relied | ||
* [ ] deployer is denied | ||
* [ ] no other address has been relied | ||
* [ ] `RwaUrn`/`RwaUrn2` | ||
* [ ] contract is verified on etherscan | ||
* [ ] ensure `0.6.12` solc version is used | ||
* [ ] ensure optimizations are off | ||
* [ ] ensure license is specified (SPDX in code or otherwise) | ||
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/tree/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/urns) and it's consistent with previous RWA onboardings | ||
* [ ] constructor args are correct and match [Chainlog](https://chainlog.makerdao.com/) | ||
* [ ] `vat` matches `MCD_VAT` | ||
* [ ] `jug` matches `MCD_JUG` | ||
* [ ] `gemJoin` matches `MCD_JOIN_RWAXYZ_A` (Per spell code) | ||
* [ ] `daiJoin` matches `MCD_JOIN_DAI` | ||
* [ ] `outputConduit` matches `RwaOutputConduit<2,3>` (Per spell code) | ||
* [ ] check `wards` | ||
* [ ] `MCD_PAUSE_PROXY` is relied | ||
* [ ] deployer is denied | ||
* [ ] no other address has been relied | ||
* [ ] `RwaJar` | ||
* [ ] contract is verified on etherscan | ||
* [ ] ensure `0.6.12` solc version is used | ||
* [ ] ensure optimizations are off | ||
* [ ] ensure license is specified (SPDX in code or otherwise) | ||
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/blob/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/jars/RwaJar.sol) and it's consistent with previous RWA onboarding | ||
* [ ] constructor arg matches [`ChainLog`](https://chainlog.makerdao.com/) | ||
* [ ] `chainlog` | ||
* [ ] no `wards` | ||
* [ ] `RwaInputConduit<2>`/`RwaSwapInputConduit<2>` | ||
* [ ] contract is verified on etherscan | ||
* [ ] ensure `0.6.12` solc version is used | ||
* [ ] ensure optimizations are off | ||
* [ ] ensure license is specified (SPDX in code or otherwise) | ||
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/tree/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/conduits) and it's consistent with previous RWA onboarding | ||
* [ ] constructor args are correct and match [chainlog](https://chainlog.makerdao.com/) | ||
* [ ] `dai` | ||
* [ ] `to` (`RwaUrn`, `RwaJar`) | ||
* [ ] `gov` (`v1`) | ||
* [ ] `psm`, `gem` (`v3`) | ||
* [ ] check `wards` | ||
* [ ] `MCD_PAUSE_PROXY` is relied | ||
* [ ] deployer is denied | ||
* [ ] no other address has been relied | ||
* [ ] `RwaOutputConduit<2>`/`RwaSwapOutputConduit` | ||
* [ ] contract is verified on etherscan | ||
* [ ] ensure `0.6.12` solc version is used | ||
* [ ] ensure optimizations are off | ||
* [ ] ensure license is specified (SPDX in code or otherwise) | ||
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/tree/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/conduits) and it's consistent with previous RWA onboarding | ||
* [ ] constructor args are correct and match [chainlog](https://chainlog.makerdao.com/) | ||
* [ ] `dai` | ||
* [ ] `gov` (`v1`) | ||
* [ ] `psm`, `gem` (`v3`) | ||
* [ ] check `wards` | ||
* [ ] `MCD_PAUSE_PROXY` is relied | ||
* [ ] deployer is denied | ||
* [ ] no other address has been relied | ||
* [ ] Risk Parameters Match Doc | ||
* [ ] `duty`(stability fee) | ||
* [ ] `line`(debt ceiling) | ||
* [ ] `mat` (liquidation ratio) | ||
* [ ] `val` (oracle price) | ||
* [ ] `val` is computed as `"debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"` | ||
* [ ] `val` matches locally executable formula (e.g. `// bc -l <<< 'scale=18; 50000000 * e(l(1.07) * (3342/365)) * 1.00' | cast --to-wei`) | ||
* [ ] `tau` (pre-agreed remediation period) | ||
* [ ] `doc` (IPFS Hash) | ||
* [ ] Onboarding Actions | ||
* [ ] `ilk` matches the format `RWAXYZ-A` | ||
* [ ] Sanity Checks (constructor args, public vars, ... via `require` condition) | ||
* [ ] `MIP21_LIQUIDATION_ORACLE.init` | ||
* [ ] `vat.init.ilk` | ||
* [ ] `jug.init.ilk` (this will set `duty` to `RAY` (zero pct) by default) | ||
* [ ] `vat` rely `join` | ||
* [ ] Increase Ilk Debt Ceiling (set DC + increase Global DC) | ||
* [ ] File Ilk `pip` in the `spotter` | ||
* [ ] File Ilk `mat` in the `spotter` | ||
* [ ] Poke `spotter` to pull in the price | ||
* [ ] `join` rely `urn` | ||
* [ ] Access Control | ||
* [ ] `hope` (operator, pause proxy) | ||
* [ ] `mate` (operator, pause proxy as fallback if required) | ||
* [ ] `kiss` (whitelist for `urn` destination address `who`) | ||
* [ ] Fileable (`RwaSwapOutputConduit` and `RwaSwapInputConduit`) | ||
* [ ] `quitTo` (`file` the appropriate address for conduits per technical assessment) | ||
* [ ] New Chainlog Entries | ||
* [ ] `RWAXYZ` | ||
* [ ] `PIP_RWAXYZ` precomputed via `cast compute-address $MIP21_LIQUIDATION_ORACLE` | ||
* [ ] Note that a nonce change for `MIP21_LIQUIDATION_ORACLE` prior to casting will cause this to be incorrect | ||
* [ ] `MCD_JOIN_RWAXYZ_A` | ||
* [ ] `RWAXYZ_A_URN` | ||
* [ ] `RWAXYZ_A_JAR` | ||
* [ ] `RWAXYZ_A_INPUT_CONDUIT` | ||
* [ ] `RWAXYZ_A_OUTPUT_CONDUIT` | ||
* [ ] Chainlog Bump | ||
* [ ] Patch `x.x.1` | ||
* [ ] Add Ilk to `IlkRegistry` | ||
* [ ] `put` is used | ||
* [ ] `class` is 3 | ||
* [ ] `name` matches forum post (e.g. "RWA007-A: Monetalis Clydesdale") | ||
* [ ] Ensure `DssExecLib` is used for the Onboarding (e.g. `DssExecLib.vat`) | ||
* [ ] Test Coverage (Follow Previous Test Patterns) | ||
* [ ] `testNewChainlogValues` | ||
* [ ] `testNewIlkRegistryValues` | ||
* [ ] `testRWAXYZ_INTEGRATION_CONDUITS_SETUP` | ||
* [ ] `testRWAXYZ_INTEGRATION_BUMP` | ||
* [ ] `testRWAXYZ_INTEGRATION_TELL` | ||
* [ ] `testRWAXYZ_INTEGRATION_TELL_CURE_GOOD` | ||
* [ ] `testFailRWAXYZ_INTEGRATION_CURE_BEFORE_TELL` | ||
* [ ] `testRWAXYZ_INTEGRATION_TELL_CULL` | ||
* [ ] `testRWAXYZ_PAUSE_PROXY_OWNS_RWAXYZ_TOKEN_BEFORE_SPELL` | ||
* [ ] `testRWAXYZ_SPELL_LOCK_OPERATOR_DRAW_WIPE_FREE` | ||
* [ ] `testFailRWAXYZ_DRAW_ABOVE_LINE` | ||
* [ ] `testFailRWAXYZ_OUTPUT_CONDUIT_PUSH_ABOVE_BALANCE` | ||
* [ ] `testRWAXYZ_OPERATOR_LOCK_DRAW_CAGE` | ||
* [ ] `testRWAXYZ_SPELL_LOCK` | ||
* [ ] `addresses_<mainnet, goerli>.sol` | ||
* [ ] `config.sol` | ||
|
||
## RWA Update Checklist | ||
|
||
* IF `doc` is updated | ||
* [ ] [`_updateDoc` helper](https://github.com/makerdao/spells-mainnet/blob/7400e91c4f211fc24bd4d3a95a86416afc4df9d1/archive/2023-09-27-DssSpell/DssSpell.sol#L76-L87) is copied one-to-one from the archive and defined above `actions` | ||
* [ ] `_updateDoc(ilk, doc)` is called in the spell | ||
* IF debt ceiling is updated | ||
* IF AutoLine update is requested by the Exec Sheet | ||
* [ ] Parameters are set via [`DssExecLib.setIlkAutoLineParameters(ilk, amount, gap, ttl)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L648) or [`DssExecLib.setIlkAutoLineDebtCeiling(ilk, amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L658) | ||
* IF regular debt ceiling (`vat.ilk.line`) update is requested by the Exec Sheet | ||
* [ ] Collateral type (`ilk`) have [`AutoLine`](https://github.com/makerdao/dss-auto-line/tree/master) disabled previously or in the spell | ||
* [ ] Debt ceiling (`vat.ilk.line`) is updated, via EITHER: | ||
* [`DssExecLib.increaseIlkDebtCeiling(ilk, amount, global)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L621C14-L621C36) | ||
* [`DssExecLib.decreaseIlkDebtCeiling(ilk, amount, global)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L634) | ||
* [`DssExecLib.setIlkDebtCeiling(ilk, amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L611) | ||
* [ ] Global debt ceiling (`vat.Line`) is updated accordingly, UNLESS specifically instructed not to, via EITHER: | ||
* `global` set to `true` in `increaseIlkDebtCeiling`/`decreaseIlkDebtCeiling` | ||
* [`DssExecLib.setGlobalDebtCeiling(amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L428) | ||
* [`DssExecLib.increaseGlobalDebtCeiling(amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L436) | ||
* [`DssExecLib.decreaseGlobalDebtCeiling(amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L445C14-L445C39) | ||
* [ ] Liquidation oracle price is bumped via `RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).bump(ilk, val)` pattern | ||
* [ ] Comment above `bump` explains `val` computation via `// Note: the formula is: "debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"` | ||
* [ ] Comment above `bump` provides locally executable formula (e.g. `// bc -l <<< 'scale=18; 50000000 * e(l(1.07) * (3342/365)) * 1.00' | cast --to-wei`) | ||
* [ ] The formula matches the example provided above | ||
* [ ] `debt_ceiling` in the executable formula matches new debt ceiling set in the spell or the maximum possible debt ceiling in case of the enabled AutoLine | ||
* [ ] `rwa_stability_fee` in the executable formula matches stability fee of the specified RWA found on chain | ||
* [ ] `minimum_deal_duration_in_years` in the executable formula matches number found in the Exec Sheet of the spell containing relevant RWA onboarding | ||
* [ ] `liquidation_ratio` in the executable formula matches liquidation ratio of the specified RWA found on chain | ||
* [ ] Executing formula locally provides integer number that matches the `val` in the spell | ||
* [ ] `val` makes sense in context of the [rate mechanism](https://github.com/makerdao/developerguides/blob/master/mcd/intro-rate-mechanism/intro-rate-mechanism.md) | ||
* [ ] IF multiple RWA ilks are being combined into one, `val` calculation is done once per ilk and added to make the total, with separate executable formulas provided in comments. The existing `val` value can be retrieved by calling `read()` on `PIP_RWAXYZ` and converting the result into decimal | ||
* [ ] Oracle price is updated via `DssExecLib.updateCollateralPrice(ilk)` | ||
* IF soft liquidation explicitly requested to be triggered (via `.tell(ilk)`) AND debt ceiling (`vat.ilks(ilk).line`) is `0` (OR is being set to `0` in the current spell) | ||
* [ ] `RwaLiquidationOracle.tell(ilk)` call is present | ||
* [ ] IF `RWAXYZ_A_INPUT_CONDUIT` is an instance of [`TinlakeMgr`](https://github.com/centrifuge/tinlake-maker-lib/blob/master/src/mgr.sol) (it is a Centrifuge integration), additional `TinlakeMgr.tell()` call is present (in order to prevent further `TIN` redemptions in the Centrifuge pool) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has been in the Could you guide me where I can find related code or help me understand why this is needed? |
||
|
||
## RWA Offboarding Checklist | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we require removal from the IlkRegistry here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing is that we usually don't remove anything from the ilk registry. I'm not sure if we should do it for this specific case only. |
||
|
||
* IF there is debt in the RWA Vault (`vat.urns(ilk, RWAXYZ_A_URN).art > 0`), proceed with the write-off (i.e.: vault is in default): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a situation where the RWA Vault has surplus when being offboarded? In this case, what should be done with it? (send it to surplus buffer?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by surplus? |
||
* IF soft liquidation `.tell(ilk)` has **NOT** been called for the ilk in a previous spell: | ||
* [ ] The value of `RwaLiquidationOracle.ilks(ilk).tau` MUST be zero, OTHERWISE the offboarding can only happen in a future spell. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the rest of checklist still happen except There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it makes sense. I'll amend this. |
||
* [ ] The debt ceiling (`vat.ilks(ilk).line`) is `0` OR is currently being set to `0`. | ||
* [ ] `RwaLiquidationOracle.tell(ilk)` call is present | ||
* [ ] IF `RWAXYZ_A_INPUT_CONDUIT` is an instance of [`TinlakeMgr`](https://github.com/centrifuge/tinlake-maker-lib/blob/master/src/mgr.sol) (it is a Centrifuge integration), additional `TinlakeMgr.tell()` call is present (in order to prevent further `TIN` redemptions in the Centrifuge pool) | ||
* [ ] IF the stability fee for the ilk is not zero (`jug.ilks(ilk).duty > 1 * RAY`), `jug.drip(ilk)` call is present | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could there be a case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes... All Centrifuge vaults have non-zero stability fees, and some of them have been put under soft liquidation. |
||
* [ ] `RwaLiquidationOracle.cull(ilk, RWAXYZ_A_URN)` call is present | ||
* OTHERWISE IF there is no more debt remaining in the vault (`vat.urns(ilk, RWAXYZ_A_URN).art == 0`): | ||
* [ ] The debt ceiling (`vat.ilks(ilk).line`) is currently being set to `0`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we deny the Join on the Vat? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RWAs gem joins are permissioned, so in theory there's no harm in leaving the permission there. |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: Should we sanity check if the price is reasonable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's actually a correct way to calculate it. We should probably add it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pe-checklists/archived/spell/spell-reviewer-goerli-checklist.md
Lines 189 to 195 in 1069a8a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check these.