Closed amusingaxl closed 6 months ago
Good to deploy
makerdao/community
GitHub repoExecutive vote - Month DD, YYYY.md
TARGET_DATE
, generate Exec Doc Hash via make exec-hash date=$TARGET_DATE $URL
Insert your Exec Doc Hash here
Script fails to run (known issue on non-linux OSs), manually generated hash: 0x8f7a9272969cd40df959c70acaa5205edd339294bd96007d95776ac897fca331cast keccak -- "$(curl '$URL' -o - 2>/dev/null)"
Insert your Exec Doc Hash here 0x8f7a9272969cd40df959c70acaa5205edd339294bd96007d95776ac897fca3310.8.16
true
IF spell introduces a major change that can affect external parties (e.g.: keepers are affected in case of collateral offboarding) OTHERWISE explicitly set to false
block.timestamp + 30 days
)TARGET_DATE MakerDAO Executive Spell | Hash: EXEC_DOC_HASH
TARGET_DATE
in the description matches the Exec Doc target date// Hash: cast keccak -- "$(wget 'EXEC_DOC_URL' -q -O - 2>/dev/null)"
// ----- Section text -----
)// Instruction text
// Note:
(e.g.: // Note: Payments are skipped on goerli
)chainlog
version bump), the necessity of it is explained in the comment above prefixed with // Note:
Reasoning URL
and Authority URL
is present in the spell code under relevant section or instruction (depending on which row the url is present)Reasoning URL
and Authority URL
have prefix derived from the url itself
// Executive Vote:
if URL starts with https://vote.makerdao.com/executive/
// Poll:
if URL starts with https://vote.makerdao.com/polling/
// Forum:
if URL starts with https://forum.makerdao.com/t/
// MIP:
if URL starts with https://mips.makerdao.com/mips/details/
foundryup
rm -rf ./lib && git submodule update --init --recursive
Submodule path 'lib/dss-exec-lib': checked out '69b658f35d8618272cd139dfc18c5713caf6b96b'
Submodule path 'lib/dss-exec-lib/lib/dss-interfaces': checked out '9bfd7afadd1f8c217ef05850b2555691786286cb'
Submodule path 'lib/dss-exec-lib/lib/forge-std': checked out '0aa99eb8456693c015350c5e6c4f442ebe912f77'
Submodule path 'lib/dss-exec-lib/lib/forge-std/lib/ds-test': checked out 'cd98eff28324bfac652e63a239a60632a761790b'
Submodule path 'lib/dss-test': checked out '36ff4adbcb35760614e0d2df864026991c23d028'
Submodule path 'lib/dss-test/lib/dss-interfaces': checked out '9bfd7afadd1f8c217ef05850b2555691786286cb'
Submodule path 'lib/dss-test/lib/forge-std': checked out '155d547c449afa8715f538d69454b83944117811'
Submodule path 'lib/dss-test/lib/forge-std/lib/ds-test': checked out 'e282159d5170298eb2455a6c05280ab5a73a4ef0'
dss-exec-lib
is synced as welldss-exec-lib
(run git submodule status
) matches the latest release version or newerdss-interfaces
library used inside lib/dss-exec-lib
matches submodule used inside lib/dss-test
dss-interfaces
dss-interfaces
import "dss-interfaces/dss/VatAbstract.sol";
)dss-interfaces
, OTHERWISE should be imported from therecast interface <contract_address>
commandLike
suffix (e.g. VatLike
)WAD = 10 ** 18
RAY = 10 ** 27
RAD = 10 ** 45
internal
constant
HUNDRED = 10 ** 2
THOUSAND = 10 ** 3
MILLION = 10 ** 6
BILLION = 10 ** 9
internal
constant
make rates pct=<pct>
(e.g. pct=0.75, for 0.75%)X_PT_Y_Z_PCT_RATE
(e.g. ZERO_PT_SEVEN_FIVE_PCT_RATE
for 0.75%)internal
constant
UTC
timezoneUTC
timezoneMMM_DD_YYYY
(e.g. JAN_01_2023
for 2023-01-01)23:59:59 UTC
for the final day of something, 00:00:00 UTC
for the first day of something)internal
constant
GNU AGPLv3
licensevat
, dai
, dog
, ...)wards
or access controlPAUSE_PROXY
address was relied
(wards(PAUSE_PROXY)
is 1
)denied
(wards(deployer)
is 0
)MCD_ESM
address is already relied OR being relied
(wards(MCD_ESM)
is 1
) in this spell (as approved by Governance Facilitators, in order to allow de-authing the pause proxy during Emergency Shutdown, via denyProxy
)Rely
events except for PAUSE_PROXY
and MCD_ESM
(using a block explorer like etherscan)code --diff etherscan.sol github.sol
)addresses_deployers.sol
jug.ilk.duty
) is updatedDssExecLib.setIlkStabilityFee(ilk, rate, doDrip)
) is used// Increase ILK-A Stability Fee by X.XX% from X.XX% to X.XX%
pot.dsr
) is updatedDssExecLib.setDSR(rate, doDrip)
) is used// Increase DSR by X.XX% from X.XX% to X.XX%
make rates pct=<pct>
(e.g. pct=0.75, for 0.75%)spotter.ilk.mat
is updated, (DssExecLib.setIlkLiquidationRatio(ilk, pct_bps)
) is useddog.ilk.hole
is updated, (DssExecLib.setIlkMaxLiquidationAmount(ilk, amount)
) is usedvat.ilk.dust
is updated, (DssExecLib.setIlkMinVaultAmount(ilk, amount)
) is useddog.ilk.chop
is updated, (DssExecLib.setIlkLiquidationPenalty(ilk, pct_bps)
) is usedclip.buf
is updated, (DssExecLib.setStartingPriceMultiplicativeFactor(ilk, pct_bps)
) is usedclipperMom.clip.tolerance
is updated, (DssExecLib.setLiquidationBreakerPriceTolerance(clip, pct_bps)
) is usedclip.tail
is updated, (DssExecLib.setAuctionTimeBeforeReset(ilk, duration)
) is usedclip.cusp
is updated, (DssExecLib.setAuctionPermittedDrop(ilk, pct_bps)
) is usedclip.chip
is updated, (DssExecLib.setKeeperIncentivePercent(ilk, pct_bps)
) is usedclip.tip
is updated, (DssExecLib.setKeeperIncentiveFlatRate(ilk, amount)
) is usedcalc.tau
is updated, (DssExecLib.setLinearDecrease(calc, duration)
) is usedcalc.cut
or calc.step
are updated, DssExecLib.setStairstepExponentialDecrease(calc, duration, pct_bps)
is usedilk
) have AutoLine enabled (MCD_IAM_AUTO_LINE
)0
MCD_IAM_AUTO_LINE
) via DssExecLib.removeIlkFromAutoLine(ilk)
MCD_IAM_AUTO_LINE
) is present in the Exec Sheet0
via DssExecLib.setIlkDebtCeiling(ilk, amount)
vat.Line
) is updated accordingly, UNLESS specifically instructed not toAutoLine
parameters are updatedDssExecLib.setIlkAutoLineDebtCeiling(ilk, amount)
DssExecLib.setIlkAutoLineParameters(ilk, amount, gap, ttl)
vat.ilk.line
) is updatedilk
) have AutoLine
disabled previously or in the spellvat.Line
) is updated accordingly, UNLESS specifically instructed not to, via EITHER:global
set to true
in increaseIlkDebtCeiling
/decreaseIlkDebtCeiling
DssExecLib.setGlobalDebtCeiling(amount)
DssExecLib.increaseGlobalDebtCeiling(amount)
DssExecLib.decreaseGlobalDebtCeiling(amount)
ilk
) is removed from AutoLine (MCD_IAM_AUTO_LINE
) IF currently enabledvat.ilk.line
) is set to 0
vat.Line
) decreased by the total amount of offboarded ilkschop
) is set to 0
IF requested by governancetip
) is set to 0
IF requested by governancechip
) is set to 0
IF requested by governancehole
) is adjusted via DssExecLib.setIlkMaxLiquidationAmount(ilk, amount)
IF requested by governanceMCD_CLIP_
) is active (i.e. stopped
is 0
)spotter.ilk.mat
) being set very high in the spell (using DssExecLib.setValue(DssExecLib.spotter(), ilk, "mat", ratio)
)DssExecLib.linearInterpolation(name, target, ilk, what, startTime, start, end, duration)
)name
format matches "XXX-X Offboarding"target
matches DssExecLib.spotter()
addressilk
format matches collateral type (ilk
) name ("XXX-X"
)what
matches string "mat"
startTime
matches block.timestamp
start
uses variable CURRENT_XXX_A_MAT
start
matches current spotter.ilk.mat
valueend
uses variable TARGET_XXX_A_MAT
end
value matches the instructionend
allows liquidation of all remaining vaults (end
is bigger than collateral_type_collateralization_ratio * risk_multiplier_factor
)duration
matches the instructionDssExecLib.updateCollateralPrice(ilk)
IF collateral have no running oracle (i.e. relevant PIP_
contract have outdated zzz
value)_checkIlkClipper
helperdoc
is updated_updateDoc
helper is copied one-to-one from the archive and defined above actions
_updateDoc(ilk, doc)
is called in the spellDssExecLib.setIlkAutoLineParameters(ilk, amount, gap, ttl)
or DssExecLib.setIlkAutoLineDebtCeiling(ilk, amount)
vat.ilk.line
) update is requested by the Exec Docilk
) have AutoLine
disabled previously or in the spellvat.ilk.line
) is updated, via EITHER:vat.Line
) is updated accordingly, UNLESS specifically instructed not to, via EITHER:global
set to true
in increaseIlkDebtCeiling
/decreaseIlkDebtCeiling
DssExecLib.setGlobalDebtCeiling(amount)
DssExecLib.increaseGlobalDebtCeiling(amount)
DssExecLib.decreaseGlobalDebtCeiling(amount)
RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).bump(ilk, val)
patternbump
explains val
computation via // Note: the formula is: "debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"
bump
provides locally executable formula (e.g. // bc -l <<< 'scale=18; 50000000 * e(l(1.07) * (3342/365)) * 1.00' | cast --to-wei
)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 AutoLinerwa_stability_fee
in the executable formula matches stability fee of the specified RWA found on chainminimum_deal_duration_in_years
in the executable formula matches number found in the Exec Doc of the spell containing relevant RWA onboardingliquidation_ratio
in the executable formula matches liquidation ratio of the specified RWA found on chainval
in the spellval
makes sense in context of the rate mechanismval
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_RWAXX
and converting the result into decimalDssExecLib.updateCollateralPrice(ilk)
.tell(ilk)
) AND debt ceiling is 0
(OR is being set to 0
in the current spell)RwaLiquidationOracle.tell(ilk)
call is presentRWAXX_A_INPUT_CONDUIT
is an instance of TinlakeMgr
(it is a Centrifuge integration), additional TinlakeMgr.tell()
call is present (in order to prevent further TIN
redemptions in the Centrifuge pool)MKR
transfers are presentaddresses_wallets.sol
ether
keywordether
keyword is used, comment is present on the same line // Note: ether is a keyword helper, only MKR is transferred here
testMKRPayments
testtestMKRPayments
matches number in the Exec DocDAI
surplus buffer transfers are presentaddresses_wallets.sol
testDAIPayments
testtestDAIPayments
matches number in the Exec DocMKR
or DAI
streams (DssVest
) are createdVestAbstract
interface is imported from dss-interfaces/dss/VestAbstract.sol
restrict
is used for each stream, UNLESS otherwise explicitly stated in the Exec Docusr
(Vest recipient address) matches Exec Docusr
address in the instruction is in the checksummed formatusr
address variable name match one found in addresses_wallets.sol
tot
(Total stream amount) matches Exec Docether
keyword is used, comment is present on the same line // Note: ether is a keyword helper, only MKR is transferred here
bgn
(Vest start timestamp) matches Exec Doctau
is expressed as bgn - fin
(i.e. MONTH_DD_YYYY - MONTH_DD_YYYY
)fin
(Vest end timestamp) matches Exec Doceta
(Vest cliff duration) matches the following logiceta
is explicitly specified in the Exec Doc, then the values matcheta
and clf
(Cliff end timestamp) are not specified in the Exec Doc, then eta
is 0
clf
is specified, but clf <= bgn
, then eta
is 0
clf
is specified and clf > bgn
, eta
is expressed as clf - bgn
(i.e. MONTH_DD_YYYY - MONTH_DD_YYYY
)mgr
(Vest manager address) is specified in the Exec Doc, matches the value, OTHERWISE matches address(0)
cap
) is enough for the new streams~~
tot
divided by tau
) <=
the maximum vest streaming rate (cap
)tot
divided by tau
) >
the maximum vest streaming rate (cap
)cap
value equal to 10% greater than the new maximum vesting rate, then round new cap
up with 2 significant figure precision (i.e. 2446 becomes 2500)cap
) is changed in the spelltotal
(the sum of all tot
values)testVestDAI
or testVestMKR
MKR
or DAI
vest termination (Yank
) is presentMCD_VEST_MKR_TREASURY
chainlog address is used for MKR stream yank
MCD_VEST_DAI
chainlog address is used for DAI stream yank
testYankDAI
or testYankMKR
ProxyLike(SUBDAO_PROXY).exec(SUBDAO_SPELL, abi.encodeWithSignature("execute()"));
addresses_deployers.sol
as an entryDelegateCall
context)vat
, etc. (Check comprehensively where the risk is high)PAUSE_PROXY
as their admin
(i.e. the party that can upgrade)admin
that is not PAUSE_PROXY
are not authed on any core contracts (Blocking)delegatecall
CREATE2
(e.g. if it looks like a vanity address) do not have selfdestruct
in their codeaddresses_mainnet.sol
testNewOrUpdatedChainlogValues
public
/internal
immutable
visibility is only used when fetching addresses from the ChainLog
via DssExecLib.getChangelogAddress(key)
and constant
is used instead for static addresses
address
and wrap with Like
suffix interfaces inline (when making calls), UNLESS archive patterns permit otherwise (Such as MKR
)DssExecLib.vat()
)ChainLog
, the variable name must match the value of the ChainLog key for that address (e.g. MCD_VAT
rather than vat
), except where the archive pattern differs from this pattern (e.g. MKR)DssExecLib.address
file is not being modified by the spell PRpublic
skipped
modifier; OTHERWISE, it MUST have the skipped
modifiertestDaoResolutions()
printenv | grep "FOUNDRY_\|DAPP_"
)make test
[PASS]
prefix._Insert your local test logs here_
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x8De6DDbCd5053d32292AAA0D2105A32d108484a6
[⠢] Compiling...
[⠢] Compiling 4 files with 0.8.16
[⠆] Solc 0.8.16 finished in 4.92s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 523052)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 9.78s (7.75s CPU time)
Ran 33 tests for src/DssSpell.t.sol:DssSpellTest
[SKIP] testBytecodeMatches() (gas: 0)
[PASS] testCastCost() (gas: 377706)
[PASS] testCastOnTime() (gas: 374624)
[SKIP] testChainlogIntegrity() (gas: 0)
[PASS] testChainlogValues() (gas: 8752844)
[SKIP] testCollateralIntegrations() (gas: 0)
[PASS] testContractSize() (gas: 11139)
[SKIP] testDAIPayments() (gas: 0)
[PASS] testDaoResolutions() (gas: 13112)
[PASS] testDeployCost() (gas: 1359177)
[SKIP] testEsmAuth() (gas: 0)
[PASS] testGeneral() (gas: 25860784)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 353840)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 13444)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 1813360)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17521)
[SKIP] testSparkSpellIsExecuted() (gas: 0)
[PASS] testUseEta() (gas: 352506)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
Suite result: ok. 12 passed; 0 failed; 21 skipped; finished in 289.75s (564.01s CPU time)
Ran 2 test suites in 290.71s (299.53s CPU time): 14 tests passed, 0 failed, 21 skipped (35 total tests)
Spell is deployed to 0x6cd68b55cdc991938D95D6995d97eB807AAEAE44
.
Spell was cast on Tenderly: https://dashboard.tenderly.co/explorer/vnet/9d516650-5519-4586-9f94-14a2e09704ec
Good to deploy :)
Good to handover :D
false
UNLESS the contract size is too big AND all mitigation strategies (i.e.: removing revert strings) have failedmake diff-deployed-spell
or manually)make check-deployed-spell
DssExecLib.address
filedeployed_spell_created
matches deployment timestamp
This throws an error but the manual check matchesdeployed_spell_block
matches deployment block number
This throws an error but the manual check matchesmake deploy-info tx=<tx>
matches config
deployed_spell_created
timestampdeployed_spell_block
block numberDssExecLib.address
file (e.g. look under the 'Files Changed' PR tab, etc.)Libraries Used
matches DssExecLib Latest Releasemake diff-archive-spell
for current date or make diff-archive-spell date="YYYY-MM-DD"
DssExecLib.address
file is not being modified by the spell PRprintenv | grep "FOUNDRY_\|DAPP_"
)make test
_Insert your local test logs here_
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x8De6DDbCd5053d32292AAA0D2105A32d108484a6
[⠢] Compiling...
[⠊] Compiling 4 files with 0.8.16
[⠒] Solc 0.8.16 finished in 2.81s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 523052)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 13.22s (10.70s CPU time)
Ran 33 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1371018)
[PASS] testCastCost() (gas: 377706)
[PASS] testCastOnTime() (gas: 374624)
[SKIP] testChainlogIntegrity() (gas: 0)
[PASS] testChainlogValues() (gas: 8752844)
[SKIP] testCollateralIntegrations() (gas: 0)
[SKIP] testContractSize() (gas: 0)
[SKIP] testDAIPayments() (gas: 0)
[PASS] testDaoResolutions() (gas: 13112)
[SKIP] testDeployCost() (gas: 0)
[SKIP] testEsmAuth() (gas: 0)
[PASS] testGeneral() (gas: 25862881)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 353840)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 13444)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 1813360)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17521)
[SKIP] testSparkSpellIsExecuted() (gas: 0)
[PASS] testUseEta() (gas: 352506)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
Suite result: ok. 11 passed; 0 failed; 22 skipped; finished in 385.49s (757.85s CPU time)
Ran 2 test suites in 386.60s (398.70s CPU time): 13 tests passed, 0 failed, 22 skipped (35 total tests)
Good to handover:
false
UNLESS the contract size is too big AND all mitigation strategies (i.e.: removing revert strings) have failedmake diff-deployed-spell
or manually)make check-deployed-spell
DssExecLib.address
filedeployed_spell_created
matches deployment timestampdeployed_spell_block
matches deployment block numbermake deploy-info tx=<tx>
matches config
deployed_spell_created
timestampdeployed_spell_block
block numberDssExecLib.address
file (e.g. look under the 'Files Changed' PR tab, etc.)Libraries Used
matches DssExecLib Latest Releasemake diff-archive-spell
for current date or make diff-archive-spell date="YYYY-MM-DD"
DssExecLib.address
file is not being modified by the spell PRprintenv | grep "FOUNDRY_\|DAPP_"
)make test
_Insert your local test logs here_
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x8De6DDbCd5053d32292AAA0D2105A32d108484a6
[⠢] Compiling...
[⠃] Compiling 108 files with 0.8.16
[⠢] Solc 0.8.16 finished in 5.71s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 523052)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 9.92s (8.11s CPU time)
Ran 33 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1371018)
[PASS] testCastCost() (gas: 377706)
[PASS] testCastOnTime() (gas: 374624)
[SKIP] testChainlogIntegrity() (gas: 0)
[PASS] testChainlogValues() (gas: 8752844)
[SKIP] testCollateralIntegrations() (gas: 0)
[SKIP] testContractSize() (gas: 0)
[SKIP] testDAIPayments() (gas: 0)
[PASS] testDaoResolutions() (gas: 13112)
[SKIP] testDeployCost() (gas: 0)
[SKIP] testEsmAuth() (gas: 0)
[PASS] testGeneral() (gas: 25862881)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 353840)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 13444)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 1813360)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17521)
[SKIP] testSparkSpellIsExecuted() (gas: 0)
[PASS] testUseEta() (gas: 352506)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
Suite result: ok. 11 passed; 0 failed; 22 skipped; finished in 286.88s (558.27s CPU time)
Ran 2 test suites in 288.15s (296.80s CPU time): 13 tests passed, 0 failed, 22 skipped (35 total tests)
Good to deploy :)
Development Stage
makerdao/community
GitHub repoExecutive vote - Month DD, YYYY.md
TARGET_DATE
, generate Exec Doc Hash viamake exec-hash date=$TARGET_DATE $URL
Insert your Exec Doc Hash here :warning: The script doesn't work but the manual check matchescast keccak -- "$(curl '$URL' -o - 2>/dev/null)"
Insert your Exec Doc Hash here 0x8f7a9272969cd40df959c70acaa5205edd339294bd96007d95776ac897fca3310.8.16
true
IF spell introduces a major change that can affect external parties (e.g.: keepers are affected in case of collateral offboarding) OTHERWISE explicitly set tofalse
block.timestamp + 30 days
)TARGET_DATE MakerDAO Executive Spell | Hash: EXEC_DOC_HASH
TARGET_DATE
in the description matches the Exec Doc target date// Hash: cast keccak -- "$(wget 'EXEC_DOC_URL' -q -O - 2>/dev/null)"
// ----- Section text -----
)// Instruction text
// Note:
(e.g.:// Note: Payments are skipped on goerli
)IF action in the spell doesn't have relevant instruction (e.g.:chainlog
version bump), the necessity of it is explained in the comment above prefixed with// Note:
Reasoning URL
andAuthority URL
is present in the spell code under relevant section or instruction (depending on which row the url is present)Reasoning URL
andAuthority URL
have prefix derived from the url itself// Executive Vote:
if URL starts withhttps://vote.makerdao.com/executive/
// Poll:
if URL starts withhttps://vote.makerdao.com/polling/
// Forum:
if URL starts withhttps://forum.makerdao.com/t/
// MIP:
if URL starts withhttps://mips.makerdao.com/mips/details/
Dependency checks
foundryup
rm -rf ./lib && git submodule update --init --recursive
Submodule path 'lib/dss-exec-lib': checked out '69b658f35d8618272cd139dfc18c5713caf6b96b' Submodule path 'lib/dss-exec-lib/lib/dss-interfaces': checked out '9bfd7afadd1f8c217ef05850b2555691786286cb' Submodule path 'lib/dss-exec-lib/lib/forge-std': checked out '0aa99eb8456693c015350c5e6c4f442ebe912f77' Submodule path 'lib/dss-exec-lib/lib/forge-std/lib/ds-test': checked out 'cd98eff28324bfac652e63a239a60632a761790b' Submodule path 'lib/dss-test': checked out '36ff4adbcb35760614e0d2df864026991c23d028' Submodule path 'lib/dss-test/lib/dss-interfaces': checked out '9bfd7afadd1f8c217ef05850b2555691786286cb' Submodule path 'lib/dss-test/lib/forge-std': checked out '155d547c449afa8715f538d69454b83944117811' Submodule path 'lib/dss-test/lib/forge-std/lib/ds-test': checked out 'e282159d5170298eb2455a6c05280ab5a73a4ef0'
dss-interfaces
No unuseddss-interfaces
Only single import layout is used (e.g.import "dss-interfaces/dss/VatAbstract.sol";
)No unused static interfacesDeclared static interface not present in thedss-interfaces
, OTHERWISE should be imported from thereInterface matches deployed contract usingcast interface <contract_address>
commandInterface naming style should match withLike
suffix (e.g.VatLike
)Each static interface declare only functions actually used in the spell codePrecision units used in the spell match their defined values:WAD = 10 ** 18
RAY = 10 ** 27
RAD = 10 ** 45
Precision units match with Numerical RangesEach variable visibility is declared asinternal
Each variable state mutability is declared asconstant
Match their defined values:HUNDRED = 10 ** 2
THOUSAND = 10 ** 3
MILLION = 10 ** 6
BILLION = 10 ** 9
Match with configEach variable visibility is declared asinternal
Each variable state mutability is declared asconstant
Rates match generated locally viamake rates pct=<pct>
(e.g. pct=0.75, for 0.75%)Rates match IPFS documentRate variable name conforms toX_PT_Y_Z_PCT_RATE
(e.g.ZERO_PT_SEVEN_FIVE_PCT_RATE
for 0.75%)Rate variable visibility declared asinternal
Rate variable state mutability declared asconstant
Comment above timestamp states full date includingUTC
timezoneTimestamp converts back to the correct dateTimestamp converts back to theUTC
timezoneVariable naming matchesMMM_DD_YYYY
(e.g.JAN_01_2023
for 2023-01-01)Time of day makes logical sense in the context of timestamp usage (i.e.23:59:59 UTC
for the final day of something,00:00:00 UTC
for the first day of something)Each variable visibility is declared asinternal
Each variable state mutability is declared asconstant
Source code is verified on etherscanCompilation optimizations match deployment settings defined in the source code repoGNU AGPLv3
licenseEvery maker-related constructor argument matches chainlog (e.g.vat
,dai
,dog
, ...)wards
or access controlEnsurePAUSE_PROXY
address wasrelied
(wards(PAUSE_PROXY)
is1
)Ensure that contract deployer address wasdenied
(wards(deployer)
is0
)EnsureMCD_ESM
address is already relied OR beingrelied
(wards(MCD_ESM)
is1
) in this spell (as approved by Governance Facilitators, in order to allow de-authing the pause proxy during Emergency Shutdown, viadenyProxy
)Ensure that there are no otherRely
events except forPAUSE_PROXY
andMCD_ESM
(using a block explorer like etherscan)Source code matches corresponding github source code (e.g. diffcheck via vscodecode --diff etherscan.sol github.sol
)Deployer address is included intoaddresses_deployers.sol
jug.ilk.duty
) is updated(DssExecLib.setIlkStabilityFee(ilk, rate, doDrip)
) is usedComment matches pattern// Increase ILK-A Stability Fee by X.XX% from X.XX% to X.XX%
pot.dsr
) is updated(DssExecLib.setDSR(rate, doDrip)
) is usedComment matches pattern// Increase DSR by X.XX% from X.XX% to X.XX%
Double check that rate matchmake rates pct=<pct>
(e.g. pct=0.75, for 0.75%)Double check that rate match IPFS documentIFspotter.ilk.mat
is updated, (DssExecLib.setIlkLiquidationRatio(ilk, pct_bps)
) is usedIFdog.ilk.hole
is updated, (DssExecLib.setIlkMaxLiquidationAmount(ilk, amount)
) is usedIFvat.ilk.dust
is updated, (DssExecLib.setIlkMinVaultAmount(ilk, amount)
) is usedIFdog.ilk.chop
is updated, (DssExecLib.setIlkLiquidationPenalty(ilk, pct_bps)
) is usedIFclip.buf
is updated, (DssExecLib.setStartingPriceMultiplicativeFactor(ilk, pct_bps)
) is usedIFclipperMom.clip.tolerance
is updated, (DssExecLib.setLiquidationBreakerPriceTolerance(clip, pct_bps)
) is usedIFclip.tail
is updated, (DssExecLib.setAuctionTimeBeforeReset(ilk, duration)
) is usedIFclip.cusp
is updated, (DssExecLib.setAuctionPermittedDrop(ilk, pct_bps)
) is usedIFclip.chip
is updated, (DssExecLib.setKeeperIncentivePercent(ilk, pct_bps)
) is usedIFclip.tip
is updated, (DssExecLib.setKeeperIncentiveFlatRate(ilk, amount)
) is usedIFcalc.tau
is updated, (DssExecLib.setLinearDecrease(calc, duration)
) is usedIFcalc.cut
orcalc.step
are updated,DssExecLib.setStairstepExponentialDecrease(calc, duration, pct_bps)
is usedilk
) have AutoLine enabled (MCD_IAM_AUTO_LINE
)0
Collateral is removed from AutoLine (MCD_IAM_AUTO_LINE
) viaDssExecLib.removeIlkFromAutoLine(ilk)
The instruction to remove from AutoLine (MCD_IAM_AUTO_LINE
) is present in the Exec SheetCollateral debt ceiling is set to0
viaDssExecLib.setIlkDebtCeiling(ilk, amount)
Global debt ceiling (vat.Line
) is updated accordingly, UNLESS specifically instructed not toAutoLine
parameters are updatedEITHER is used, depending on the instruction:DssExecLib.setIlkAutoLineDebtCeiling(ilk, amount)
DssExecLib.setIlkAutoLineParameters(ilk, amount, gap, ttl)
vat.ilk.line
) is updatedCollateral type (ilk
) haveAutoLine
disabled previously or in the spellEITHER is used, depending on the instruction:DssExecLib.increaseIlkDebtCeiling(ilk, amount, global)
DssExecLib.decreaseIlkDebtCeiling(ilk, amount, global)
DssExecLib.setIlkDebtCeiling(ilk, amount)
Global debt ceiling (vat.Line
) is updated accordingly, UNLESS specifically instructed not to, via EITHER:global
set totrue
inincreaseIlkDebtCeiling
/decreaseIlkDebtCeiling
DssExecLib.setGlobalDebtCeiling(amount)
DssExecLib.increaseGlobalDebtCeiling(amount)
DssExecLib.decreaseGlobalDebtCeiling(amount)
Insert and follow the relevant checklists below:Collateral type (ilk
) is removed from AutoLine (MCD_IAM_AUTO_LINE
) IF currently enabledCollateral debt ceiling (vat.ilk.line
) is set to0
Global debt ceiling (vat.Line
) decreased by the total amount of offboarded ilksAll actions from the 1st stage offboarding are previously taken (EITHER in the current or past spells – check the archive)Collateral liquidation penalty (chop
) is set to0
IF requested by governanceFlat keeper incentive (tip
) is set to0
IF requested by governanceRelative keeper incentive (chip
) is set to0
IF requested by governanceMax liquidation amount (hole
) is adjusted viaDssExecLib.setIlkMaxLiquidationAmount(ilk, amount)
IF requested by governanceRelevant clipper contract (MCD_CLIP_
) is active (i.e.stopped
is0
)Liquidations are triggered via (depending on governance instruction):spotter.ilk.mat
) being set very high in the spell (usingDssExecLib.setValue(DssExecLib.spotter(), ilk, "mat", ratio)
)DssExecLib.linearInterpolation(name, target, ilk, what, startTime, start, end, duration)
)Ensurename
format matches "XXX-X Offboarding"Ensuretarget
matchesDssExecLib.spotter()
addressEnsureilk
format matches collateral type (ilk
) name ("XXX-X"
)Ensurewhat
matches string"mat"
EnsurestartTime
matchesblock.timestamp
Ensurestart
uses variableCURRENT_XXX_A_MAT
Ensurestart
matches currentspotter.ilk.mat
valueEnsureend
uses variableTARGET_XXX_A_MAT
Ensureend
value matches the instructionEnsureend
allows liquidation of all remaining vaults (end
is bigger thancollateral_type_collateralization_ratio * risk_multiplier_factor
)Ensureduration
matches the instructionSpotter price is updated viaDssExecLib.updateCollateralPrice(ilk)
IF collateral have no running oracle (i.e. relevantPIP_
contract have outdatedzzz
value)Spotter price is updated after all other actionsOffboarding is tested at least via_checkIlkClipper
helperdoc
is updated_updateDoc
helper is copied one-to-one from the archive and defined aboveactions
_updateDoc(ilk, doc)
is called in the spellParameters are set viaDssExecLib.setIlkAutoLineParameters(ilk, amount, gap, ttl)
orDssExecLib.setIlkAutoLineDebtCeiling(ilk, amount)
ular debt ceiling (vat.ilk.line
) update is requested by the Exec DocCollateral type (ilk
) haveAutoLine
disabled previously or in the spellDebt ceiling (vat.ilk.line
) is updated, via EITHER:DssExecLib.increaseIlkDebtCeiling(ilk, amount, global)
DssExecLib.decreaseIlkDebtCeiling(ilk, amount, global)
DssExecLib.setIlkDebtCeiling(ilk, amount)
Global debt ceiling (vat.Line
) is updated accordingly, UNLESS specifically instructed not to, via EITHER:global
set totrue
inincreaseIlkDebtCeiling
/decreaseIlkDebtCeiling
DssExecLib.setGlobalDebtCeiling(amount)
DssExecLib.increaseGlobalDebtCeiling(amount)
DssExecLib.decreaseGlobalDebtCeiling(amount)
Liquidation oracle price is bumped viaRwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).bump(ilk, val)
patternComment abovebump
explainsval
computation via// Note: the formula is: "debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"
Comment abovebump
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 abovedebt_ceiling
in the executable formula matches new debt ceiling set in the spell or the maximum possible debt ceiling in case of the enabled AutoLinerwa_stability_fee
in the executable formula matches stability fee of the specified RWA found on chainminimum_deal_duration_in_years
in the executable formula matches number found in the Exec Doc of the spell containing relevant RWA onboardingliquidation_ratio
in the executable formula matches liquidation ratio of the specified RWA found on chainExecuting formula locally provides integer number that matches theval
in the spellval
makes sense in context of the rate mechanismIF 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 existingval
value can be retrieved by callingread()
onPIP_RWAXX
and converting the result into decimalOracle price is updated viaDssExecLib.updateCollateralPrice(ilk)
.tell(ilk)
) AND debt ceiling is0
(OR is being set to0
in the current spell)RwaLiquidationOracle.tell(ilk)
call is presentIFRWAXX_A_INPUT_CONDUIT
is an instance ofTinlakeMgr
(it is a Centrifuge integration), additionalTinlakeMgr.tell()
call is present (in order to prevent furtherTIN
redemptions in the Centrifuge pool)MKR
transfers are presentRecipient address in the instruction is in the checksummed formatRecipient address matches Exec DocRecipient address variable name matches one found inaddresses_wallets.sol
Transfer amount matches Exec DocTransfer amount is specified with (at least) 2 decimals usingether
keywordIFether
keyword is used, comment is present on the same line// Note: ether is a keyword helper, only MKR is transferred here
The transfers are tested viatestMKRPayments
testSum of all MKR transfers tested intestMKRPayments
matches number in the Exec DocDAI
surplus buffer transfers are presentRecipient address in the instruction is in the checksummed formatRecipient address matches Exec DocRecipient address variable name matches one found inaddresses_wallets.sol
Transfer amount matches Exec DocThe transfers are tested viatestDAIPayments
testSum of all DAI transfers tested intestDAIPayments
matches number in the Exec DocMKR
orDAI
streams (DssVest
) are createdVestAbstract
interface is imported fromdss-interfaces/dss/VestAbstract.sol
restrict
is used for each stream, UNLESS otherwise explicitly stated in the Exec Docusr
(Vest recipient address) matches Exec Docusr
address in the instruction is in the checksummed formatusr
address variable name match one found inaddresses_wallets.sol
tot
(Total stream amount) matches Exec DocIFether
keyword is used, comment is present on the same line// Note: ether is a keyword helper, only MKR is transferred here
IF vest amount is expressed in 'per year' or similar in the Exec Doc, account for leap daysbgn
(Vest start timestamp) matches Exec Doctau
is expressed asbgn - fin
(i.e.MONTH_DD_YYYY - MONTH_DD_YYYY
)fin
(Vest end timestamp) matches Exec Doceta
(Vest cliff duration) matches the following logiceta
is explicitly specified in the Exec Doc, then the values matcheta
andclf
(Cliff end timestamp) are not specified in the Exec Doc, theneta
is0
clf
is specified, butclf <= bgn
, theneta
is0
clf
is specified andclf > bgn
,eta
is expressed asclf - bgn
(i.e.MONTH_DD_YYYY - MONTH_DD_YYYY
)IFmgr
(Vest manager address) is specified in the Exec Doc, matches the value, OTHERWISE matchesaddress(0)
Ensure that max vesting rate (cap
) is enough for the new streamstot
divided bytau
)<=
the maximum vest streaming rate (cap
)tot
divided bytau
)>
the maximum vest streaming rate (cap
)cap
value equal to 10% greater than the new maximum vesting rate, then round newcap
up with 2 significant figure precision (i.e. 2446 becomes 2500)cap
) is changed in the spellGovernance facilitators were notifiedExec Sheet contain explicit instructionExec Doc contain explicit instructionVest contract's MKR allowance increased by the cumulativetotal
(the sum of alltot
values)Ensure allowance increase follows archive patternsTested viatestVestDAI
ortestVestMKR
MKR
orDAI
vest termination (Yank
) is presentYanked stream ID matches Exec DocMCD_VEST_MKR_TREASURY
chainlog address is used for MKR streamyank
MCD_VEST_DAI
chainlog address is used for DAI streamyank
Tested viatestYankDAI
ortestYankMKR
SubDAO spell address matches Exec DocExecuted viaProxyLike(SUBDAO_PROXY).exec(SUBDAO_SPELL, abi.encodeWithSignature("execute()"));
Execution is NOT delegate callIF SubDAO spell deployer is a smart contract (e.g. multisig or factory), ensure the deployer address is inaddresses_deployers.sol
as an entryEnsure that SubDAO spell have enough gas and does not revert with "out of gas" error inside simulation. Note: low level call gas estimation is not done by our scriptsDelegateCall
context)No SubDAO contract being interacted with is authed on a core contract likevat
, etc. (Check comprehensively where the risk is high)SubDAO contract licensing and optimizations generally do not matter (except where they pose a security risk)SubDAO contracts and all libraries / dependencies have verified source code (Blocking)Upgradable contracts have thePAUSE_PROXY
as theiradmin
(i.e. the party that can upgrade)Any upgradable SubDAO contracts with anadmin
that is notPAUSE_PROXY
are not authed on any core contracts (Blocking)All SubDAO content addresses (i.e. provided contract addresses or EOAs) present in the Maker Core spell are present in the Exec Doc and are correct. SubDAO addresses being authed or given any permissions MUST be in the Exec Doc. SubDAO addresses being called must be confirmed by the SubDAO spell team.IF addresses not PR'ed in by the SubDAO team (use git blame for example), SubDAO content addresses all have inline comment for provenance or source being OKed by SubDAOSubDAO actions match Exec Doc (only where inline with main spell code) and do not affect core contractsCore contract knock-on actions (such as offboarding or setting DC to 0) are present in the exec and match the codeExternal calls for SubDAO content are NOT delegate callCode does not have untoward behavior within the scope of Maker Core Contracts (e.g. up to the SubDAO proxy)Target Contract doesn't block spell executionExternal call is NOTdelegatecall
Target Contract doesn't have permissions on the VatTarget Contract doesn't do anything untoward (e.g. interacting with unsafe contracts)Contracts deployed viaCREATE2
(e.g. if it looks like a vanity address) do not haveselfdestruct
in their codeMCD Pause Proxy doesn't give any approvalsAll possible actions of the Target Contract are documentedTarget contract is not upgradableTarget Contract is included in the ChainLogTest Coverage is comprehensiveChainLog version is incremented based on update typeNew addresses are added to theaddresses_mainnet.sol
Changes are tested viatestNewOrUpdatedChainlogValues
public
/internal
Ensureimmutable
visibility is only used when fetching addresses from theChainLog
viaDssExecLib.getChangelogAddress(key)
andconstant
is used instead for static addressesFetch addresses as typeaddress
and wrap withLike
suffix interfaces inline (when making calls), UNLESS archive patterns permit otherwise (Such asMKR
)Use the DssExecLib Core Address Helpers where possible (e.g.DssExecLib.vat()
)Where addresses are fetched from theChainLog
, the variable name must match the value of the ChainLog key for that address (e.g.MCD_VAT
rather thanvat
), except where the archive pattern differs from this pattern (e.g. MKR)DssExecLib.address
file is not being modified by the spell PRpublic
skipped
modifier; OTHERWISE, it MUST have theskipped
modifiertestDaoResolutions
printenv | grep "FOUNDRY_\|DAPP_"
)make test
[PASS]
prefix.