Skip to content

Commit 042effd

Browse files
authored
Merge pull request #42 from makerdao/feat/rwa-offboarding
Feat: RWA Offboarding Checklist
2 parents 424c561 + 22588cc commit 042effd

File tree

4 files changed

+200
-171
lines changed

4 files changed

+200
-171
lines changed

.wordlist.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Crafter
2424
Crafter's
2525
cron
2626
CUs
27+
crypto
2728
DAI
2829
Daiwanese
2930
DAO
@@ -110,6 +111,7 @@ repos
110111
RPC
111112
RWA
112113
RWAXXX
114+
RWAXYZ
113115
setIlkAutoLineDebtCeiling
114116
setIlkAutoLineParameters
115117
setIlkDebtCeiling

spell/rwa-checklists.md

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# RWA Checklists
2+
3+
## RWA Onboarding Checklist
4+
5+
* [ ] Deployed Contracts
6+
* [ ] `RwaToken` (Token Used as Collateral In Adapter)
7+
* [ ] deployed via [`RwaTokenFactory`](https://github.com/makerdao/rwa-toolkit/blob/master/src/tokens/RwaTokenFactory.sol)
8+
* [ ] Fab matches [chainlog](https://chainlog.makerdao.com/)
9+
* [ ] 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
10+
* [ ] Rwa Token transferred to MCD Pause Proxy
11+
* [ ] `createRwaToken` parameters are correct
12+
* [ ] `name` is in `RWA-XYZ` format
13+
* [ ] `symbol` is in `RWAXYZ` format
14+
* [ ] `recipient` matches MCD Pause Proxy
15+
* [ ] `AuthGemJoin` (Join Adapter)
16+
* [ ] deployed via [JoinFab](https://github.com/makerdao/JoinFab/blob/master/src/JoinFab.sol)
17+
* [ ] Fab matches [chainlog](https://chainlog.makerdao.com/)
18+
* [ ] 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)
19+
* [ ] `newAuthGemJoin` parameters are correct
20+
* [ ] `owner` matches `PAUSE_PROXY`
21+
* [ ] `ilk` is the `bytes32` representation of "RWAXYZ-A"
22+
* [ ] `cast --to-ascii <bytes32>` matches ASCII Ilk
23+
* [ ] `cast --to-bytes32 $(cast --from-ascii "RWAXYZ-A")` matches `bytes32` (to check the amount of padding zeroes is correct)
24+
* [ ] `gem` matches `RwaToken` deployed contract
25+
* [ ] check `wards`
26+
* [ ] `MCD_PAUSE_PROXY` is relied
27+
* [ ] deployer is denied
28+
* [ ] no other address has been relied
29+
* [ ] `RwaUrn`/`RwaUrn2`
30+
* [ ] contract is verified on etherscan
31+
* [ ] ensure `0.6.12` solc version is used
32+
* [ ] ensure optimizations are off
33+
* [ ] ensure license is specified (SPDX in code or otherwise)
34+
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/tree/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/urns) and it's consistent with previous RWA onboardings
35+
* [ ] constructor args are correct and match [Chainlog](https://chainlog.makerdao.com/)
36+
* [ ] `vat` matches `MCD_VAT`
37+
* [ ] `jug` matches `MCD_JUG`
38+
* [ ] `gemJoin` matches `MCD_JOIN_RWAXYZ_A` (Per spell code)
39+
* [ ] `daiJoin` matches `MCD_JOIN_DAI`
40+
* [ ] `outputConduit` matches `RwaOutputConduit<2,3>` (Per spell code)
41+
* [ ] check `wards`
42+
* [ ] `MCD_PAUSE_PROXY` is relied
43+
* [ ] deployer is denied
44+
* [ ] no other address has been relied
45+
* [ ] `RwaJar`
46+
* [ ] contract is verified on etherscan
47+
* [ ] ensure `0.6.12` solc version is used
48+
* [ ] ensure optimizations are off
49+
* [ ] ensure license is specified (SPDX in code or otherwise)
50+
* [ ] 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
51+
* [ ] constructor arg matches [`ChainLog`](https://chainlog.makerdao.com/)
52+
* [ ] `chainlog`
53+
* [ ] no `wards`
54+
* [ ] `RwaInputConduit<2>`/`RwaSwapInputConduit<2>`
55+
* [ ] contract is verified on etherscan
56+
* [ ] ensure `0.6.12` solc version is used
57+
* [ ] ensure optimizations are off
58+
* [ ] ensure license is specified (SPDX in code or otherwise)
59+
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/tree/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/conduits) and it's consistent with previous RWA onboarding
60+
* [ ] constructor args are correct and match [chainlog](https://chainlog.makerdao.com/)
61+
* [ ] `dai`
62+
* [ ] `to` (`RwaUrn`, `RwaJar`)
63+
* [ ] `gov` (`v1`)
64+
* [ ] `psm`, `gem` (`v3`)
65+
* [ ] check `wards`
66+
* [ ] `MCD_PAUSE_PROXY` is relied
67+
* [ ] deployer is denied
68+
* [ ] no other address has been relied
69+
* [ ] `RwaOutputConduit<2>`/`RwaSwapOutputConduit`
70+
* [ ] contract is verified on etherscan
71+
* [ ] ensure `0.6.12` solc version is used
72+
* [ ] ensure optimizations are off
73+
* [ ] ensure license is specified (SPDX in code or otherwise)
74+
* [ ] ensure source matches [GitHub code](https://github.com/makerdao/rwa-toolkit/tree/8d30ed2cb657641253d45b57c894613e26b4ae1b/src/conduits) and it's consistent with previous RWA onboarding
75+
* [ ] constructor args are correct and match [chainlog](https://chainlog.makerdao.com/)
76+
* [ ] `dai`
77+
* [ ] `gov` (`v1`)
78+
* [ ] `psm`, `gem` (`v3`)
79+
* [ ] check `wards`
80+
* [ ] `MCD_PAUSE_PROXY` is relied
81+
* [ ] deployer is denied
82+
* [ ] no other address has been relied
83+
* [ ] Risk Parameters Match Doc
84+
* [ ] `duty`(stability fee)
85+
* [ ] `line`(debt ceiling)
86+
* [ ] `mat` (liquidation ratio)
87+
* [ ] `val` (oracle price)
88+
* [ ] `val` is computed as `"debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"`
89+
* [ ] `val` matches locally executable formula (e.g. `// bc -l <<< 'scale=18; 50000000 * e(l(1.07) * (3342/365)) * 1.00' | cast --to-wei`)
90+
* [ ] `tau` (pre-agreed remediation period)
91+
* [ ] `doc` (IPFS Hash)
92+
* [ ] Onboarding Actions
93+
* [ ] `ilk` matches the format `RWAXYZ-A`
94+
* [ ] Sanity Checks (constructor args, public vars, ... via `require` condition)
95+
* [ ] `MIP21_LIQUIDATION_ORACLE.init`
96+
* [ ] `vat.init.ilk`
97+
* [ ] `jug.init.ilk` (this will set `duty` to `RAY` (zero pct) by default)
98+
* [ ] `vat` rely `join`
99+
* [ ] Increase Ilk Debt Ceiling (set DC + increase Global DC)
100+
* [ ] File Ilk `pip` in the `spotter`
101+
* [ ] File Ilk `mat` in the `spotter`
102+
* [ ] Poke `spotter` to pull in the price
103+
* [ ] `join` rely `urn`
104+
* [ ] Access Control
105+
* [ ] `hope` (operator, pause proxy)
106+
* [ ] `mate` (operator, pause proxy as fallback if required)
107+
* [ ] `kiss` (whitelist for `urn` destination address `who`)
108+
* [ ] Fileable (`RwaSwapOutputConduit` and `RwaSwapInputConduit`)
109+
* [ ] `quitTo` (`file` the appropriate address for conduits per technical assessment)
110+
* [ ] New Chainlog Entries
111+
* [ ] `RWAXYZ`
112+
* [ ] `PIP_RWAXYZ` precomputed via `cast compute-address $MIP21_LIQUIDATION_ORACLE`
113+
* [ ] Note that a nonce change for `MIP21_LIQUIDATION_ORACLE` prior to casting will cause this to be incorrect
114+
* [ ] `MCD_JOIN_RWAXYZ_A`
115+
* [ ] `RWAXYZ_A_URN`
116+
* [ ] `RWAXYZ_A_JAR`
117+
* [ ] `RWAXYZ_A_INPUT_CONDUIT`
118+
* [ ] `RWAXYZ_A_OUTPUT_CONDUIT`
119+
* [ ] Chainlog Bump
120+
* [ ] Patch `x.x.1`
121+
* [ ] Add Ilk to `IlkRegistry`
122+
* [ ] `put` is used
123+
* [ ] `class` is 3
124+
* [ ] `name` matches forum post (e.g. "RWA007-A: Monetalis Clydesdale")
125+
* [ ] Ensure `DssExecLib` is used for the Onboarding (e.g. `DssExecLib.vat`)
126+
* [ ] Test Coverage (Follow Previous Test Patterns)
127+
* [ ] `testNewChainlogValues`
128+
* [ ] `testNewIlkRegistryValues`
129+
* [ ] `testRWAXYZ_INTEGRATION_CONDUITS_SETUP`
130+
* [ ] `testRWAXYZ_INTEGRATION_BUMP`
131+
* [ ] `testRWAXYZ_INTEGRATION_TELL`
132+
* [ ] `testRWAXYZ_INTEGRATION_TELL_CURE_GOOD`
133+
* [ ] `testFailRWAXYZ_INTEGRATION_CURE_BEFORE_TELL`
134+
* [ ] `testRWAXYZ_INTEGRATION_TELL_CULL`
135+
* [ ] `testRWAXYZ_PAUSE_PROXY_OWNS_RWAXYZ_TOKEN_BEFORE_SPELL`
136+
* [ ] `testRWAXYZ_SPELL_LOCK_OPERATOR_DRAW_WIPE_FREE`
137+
* [ ] `testFailRWAXYZ_DRAW_ABOVE_LINE`
138+
* [ ] `testFailRWAXYZ_OUTPUT_CONDUIT_PUSH_ABOVE_BALANCE`
139+
* [ ] `testRWAXYZ_OPERATOR_LOCK_DRAW_CAGE`
140+
* [ ] `testRWAXYZ_SPELL_LOCK`
141+
* [ ] `addresses_<mainnet, goerli>.sol`
142+
* [ ] `config.sol`
143+
144+
## RWA Update Checklist
145+
146+
* IF `doc` is updated
147+
* [ ] [`_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`
148+
* [ ] `_updateDoc(ilk, doc)` is called in the spell
149+
* IF debt ceiling is updated
150+
* IF AutoLine update is requested by the Exec Sheet
151+
* [ ] 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)
152+
* IF regular debt ceiling (`vat.ilk.line`) update is requested by the Exec Sheet
153+
* [ ] Collateral type (`ilk`) have [`AutoLine`](https://github.com/makerdao/dss-auto-line/tree/master) disabled previously or in the spell
154+
* [ ] Debt ceiling (`vat.ilk.line`) is updated, via EITHER:
155+
* [`DssExecLib.increaseIlkDebtCeiling(ilk, amount, global)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L621C14-L621C36)
156+
* [`DssExecLib.decreaseIlkDebtCeiling(ilk, amount, global)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L634)
157+
* [`DssExecLib.setIlkDebtCeiling(ilk, amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L611)
158+
* [ ] Global debt ceiling (`vat.Line`) is updated accordingly, UNLESS specifically instructed not to, via EITHER:
159+
* `global` set to `true` in `increaseIlkDebtCeiling`/`decreaseIlkDebtCeiling`
160+
* [`DssExecLib.setGlobalDebtCeiling(amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L428)
161+
* [`DssExecLib.increaseGlobalDebtCeiling(amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L436)
162+
* [`DssExecLib.decreaseGlobalDebtCeiling(amount)`](https://github.com/makerdao/dss-exec-lib/blob/v0.0.9/src/DssExecLib.sol#L445C14-L445C39)
163+
* [ ] Liquidation oracle price is bumped via `RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).bump(ilk, val)` pattern
164+
* [ ] Comment above `bump` explains `val` computation via `// Note: the formula is: "debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"`
165+
* [ ] 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`)
166+
* [ ] The formula matches the example provided above
167+
* [ ] `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
168+
* [ ] `rwa_stability_fee` in the executable formula matches stability fee of the specified RWA found on chain
169+
* [ ] `minimum_deal_duration_in_years` in the executable formula matches number found in the Exec Sheet of the spell containing relevant RWA onboarding
170+
* [ ] `liquidation_ratio` in the executable formula matches liquidation ratio of the specified RWA found on chain
171+
* [ ] Executing formula locally provides integer number that matches the `val` in the spell
172+
* [ ] `val` makes sense in context of the [rate mechanism](https://github.com/makerdao/developerguides/blob/master/mcd/intro-rate-mechanism/intro-rate-mechanism.md)
173+
* [ ] 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
174+
* [ ] Oracle price is updated via `DssExecLib.updateCollateralPrice(ilk)`
175+
* 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)
176+
* [ ] `RwaLiquidationOracle.tell(ilk)` call is present
177+
* [ ] 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)
178+
179+
## RWA Offboarding Checklist
180+
181+
* [ ] The debt ceiling (`vat.ilks(ilk).line`) is `0` OR is currently being set to `0`.
182+
* IF soft liquidation `.tell(ilk)` has **NOT** been called for the ilk in a previous spell:
183+
* [ ] `RwaLiquidationOracle.tell(ilk)` call is present
184+
* [ ] 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)
185+
* 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):
186+
* [ ] Obtain `toc` and `tau` from `RwaLiquidationOracle.ilks(ilk)`
187+
* [ ] IF `block.timestamp >= toc + tau`, then
188+
* [ ] IF the stability fee for the ilk is not zero (`jug.ilks(ilk).duty > 1 * RAY`), `jug.drip(ilk)` call is present
189+
* [ ] `RwaLiquidationOracle.cull(ilk, RWAXYZ_A_URN)` call is present
190+
* [ ] 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.cull()` call is present
191+
* [ ] OTHERWISE the write-off can only happen in a future spell

0 commit comments

Comments
 (0)