Closed amusingaxl closed 4 months ago
TLDR: Good to deploy
Disclaimer: the 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341
(MCD_LITE_PSM_USDC_A_POCKET
) address which will hold USDC tokens on behalf of LitePSM is an EOA and therefore it is technically not possible to validate that no party has access to it anymore. In the following review we trust Ecosystem as Scope Facilitator and Governance Facilitators that one of the two shards was burnt and no one will be able to move tokens from this address beyond the LitePSM contract itself.
0.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 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
ℹ️ Updated versions:
foundryup: installed - forge 0.2.0 (62cdea8 2024-07-23T00:18:49.756549000Z)
foundryup: installed - cast 0.2.0 (62cdea8 2024-07-23T00:18:49.794538000Z)
foundryup: installed - anvil 0.2.0 (62cdea8 2024-07-23T00:18:49.797288000Z)
foundryup: installed - chisel 0.2.0 (62cdea8 2024-07-23T00:18:49.797572000Z)
rm -rf ./lib && git submodule update --init --recursive
Insert checked out submodule paths here
Submodule path 'lib/dss-exec-lib': checked out '69b658f35d8618272cd139dfc18c5713caf6b96b'
Submodule path 'lib/dss-test': checked out '36ff4adbcb35760614e0d2df864026991c23d028'
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 there
:warning: PauseLike
is present as DSPauseAbstract
, but contains more methods that will be unused in this spell, so it's acceptable to re-declare the interface also by the previous conventioncast interface <contract_address>
command
ℹ️ When checked via cast interface
command, ProxyLike
doesn't match, although matches the source code – a known limitation of the 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
MCD_LITE_PSM_USDC_A
GNU AGPLv3
licensevat
, dai
, dog
, ...)
ℹ️
ilk_
(bytes32): 0x4c4954452d50534d2d555344432d410000000000000000000000000000000000
LITE-PSM-USDC-A
(matches exec sheet)gem_
(address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
USDC
address in the chainlogdaiJoin_
(address): 0x9759A6Ac90977b93B58547b4A71c78317f391A28
MCD_JOIN_DAI
address in the chainlogpocket_
(address): 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341
MCD_LITE_PSM_USDC_A_POCKET
address in the spell (see below)wards
or access control
PAUSE_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
)
:warning: Reasoning URL forum post states "LitePSM module is not supported by the ESM". ChainSecurity audit also explicitely mentions this in "8.3 DssLitePsm Does Not Support Global Settlement". Therefore it's expected that contracts related to LitePSM will not authorize MCD_ESM
addressRely
events except for PAUSE_PROXY
and MCD_ESM
(using a block explorer like etherscan)code --diff etherscan.sol github.sol
)
ℹ️ Matches, checked via
diff <(cast etherscan-source 0xf6e72Db5454dd049d0788e411b06CfAF16853042) <(wget 'https://raw.githubusercontent.com/makerdao/dss-lite-psm/2f11f4bc47d96f4ebf025a1e4a249987150f9baa/src/DssLitePsm.sol' -q -O - 2>/dev/null)
addresses_deployers.sol
MCD_LITE_PSM_USDC_A_POCKET
ℹ️ This address is EOAGNU 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
LITE_PSM_MOM
GNU AGPLv3
licensevat
, dai
, dog
, ...)wards
or access control
PAUSE_PROXY
address was relied
(wards(PAUSE_PROXY)
is 1
)
ℹ️ The owner
is set to PAUSE_PROXY
addressdenied
(wards(deployer)
is 0
)
ℹ️ There is only a single owner
possible, authority
is currently set to address(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
)
:warning: Reasoning URL forum post states "LitePSM module is not supported by the ESM". ChainSecurity audit also explicitely mentions this in "8.3 DssLitePsm Does Not Support Global Settlement". Therefore it's expected that contracts related to LitePSM will not authorize MCD_ESM
addressRely
events except for PAUSE_PROXY
and MCD_ESM
(using a block explorer like etherscan)code --diff etherscan.sol github.sol
)
ℹ️ Matches, checked via
diff <(cast etherscan-source 0x467b32b0407Ad764f56304420Cddaa563bDab425) <(wget 'https://raw.githubusercontent.com/makerdao/dss-lite-psm/2f11f4bc47d96f4ebf025a1e4a249987150f9baa/src/DssLitePsmMom.sol' -q -O - 2>/dev/null)
addresses_deployers.sol
MCD_LITE_PSM_USDC_A_JAR
GNU AGPLv3
licensevat
, dai
, dog
, ...)
ℹ️
chainlog_
(address): 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F
CHANGELOG
address in the chainlog (i.e. the chainlog address itself)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
)
ℹ️ Matches, checked manually (due to the verified source code being mutli-file)
addresses_deployers.sol
MCD_LITE_PSM_USDC_A_IN_CDT_JAR
GNU AGPLv3
licensevat
, dai
, dog
, ...)
ℹ️
_dai
(address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
MCD_DAI
address in the chainlog_gem
(address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
USDC
address in the chainlog_psm
(address): 0xf6e72Db5454dd049d0788e411b06CfAF16853042
MCD_LITE_PSM_USDC_A
address onboarded via this spell_to
(address): 0x69cA348Bd928A158ADe7aa193C133f315803b06e
MCD_LITE_PSM_USDC_A_JAR
address onboarded via this spellwards
or access control
PAUSE_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
)
ℹ️ Matches, checked manually (due to the verified source code being mutli-file)
addresses_deployers.sol
CRON_LITE_PSM_JOB
GNU AGPLv3
licensevat
, dai
, dog
, ...)
ℹ️
_sequencer
(address): 0x238b4E35dAed6100C6162fAE4510261f88996EC9
CRON_SEQUENCER
address in the chainlog_litePsm
(address): 0xf6e72Db5454dd049d0788e411b06CfAF16853042
MCD_LITE_PSM_USDC_A
address onboarded via this spell_rushThreshold
(uint256): 15000000000000000000000000
fill: Set threshold at 15M DAI
instruction in the Exec Sheet (confusingly, the instruction means rush
while specifying fill
)_cutThreshold
(uint256): 300000000000000000000000
chug: Set threshold at 300k DAI
instruction in the Exec Sheet (confusingly, the instruction means cut
while specifying chug
)_gushThreshold
(uint256): 30000000000000000000000000
trim: Set threshold at 30M DAI
instruction in the Exec Sheet (confusingly, the instruction means trim
while specifying gush
)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
)
ℹ️ Matches, checked manually (due to the verified source code being mutli-file)
addresses_deployers.sol
MCD_PAUSE.delay
is set via PauseLike(MCD_PAUSE).setDelay
(as no DssExecLib
found); 2) MCD_ESM.min
is set via DssExecLib.setValue
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 usedUpdate PSM-USDC-A DC-IAM
-related instructionsilk
) 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)
:warning: Low-level call autoLine.setIlk
is used inside DssLitePsmMigrationPhase1
library, but that is not a problem, since the library was audited and decimal unit checks (found in setIlkAutoLineParameters
) were performed manuallyvat.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)
Set up LITE-PSM-USDC-A DC-IAM
-related instructionsilk
) 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)
:warning: Low-level call autoLine.setIlk
is used inside DssLitePsmMigrationPhase1
library, but that is not a problem, since the library was audited and decimal unit checks (found in setIlkAutoLineParameters
) were performed manuallyvat.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)
LITE-PSM-USDC-A
is being added to the ILK_REGISTRY
, we're following more specific "PSM Checklist" not "Collateral Onboarding"dstWant
) matches the Exec Sheet
ℹ️ The check doesn't specify units, but it is specified as WAD
in the audited source https://github.com/makerdao/dss-lite-psm/blob/2f11f4bc47d96f4ebf025a1e4a249987150f9baa/src/deployment/phase-1/DssLitePsmMigrationPhase1.sol#L35srcKeep
) matches the Exec Sheet
ℹ️ The check doesn't specify units, but it is specified as WAD
in the audited source https://github.com/makerdao/dss-lite-psm/blob/2f11f4bc47d96f4ebf025a1e4a249987150f9baa/src/deployment/phase-1/DssLitePsmMigrationPhase1.sol#L40MCD_PSM_USDC_A.gemJoin().gem() == USDC
tin
matches the value in the Exec Sheettout
matches the value in the Exec SheetAutoLine
is updated according to the Exec SheetMCD_LITE_PSM_USDC_A.gem() == USDC
or MCD_LITE_PSM_USDC_A.gemJoin().gem() == USDC
tin
matches the value in the Exec Sheettout
matches the value in the Exec SheetAutoLine
is updated according to the Exec Sheetbuf
matches the value in the Exec Sheetfill
is called conditionally (if(rush() > 0)
) to ensure liquidity is immediately available after spell executionvat.urns(DST_ILK, dstPsm).art
is increased at least by the moved amountgem
balance of dstPocket
is increased exactly by the moved amountdstPsm
is equal to dstBuf
, UNLESS limited by the debt ceiling (line
)vat.urns(SRC_ILK, srcPsm).art
is decreased exactly by the moved amountvat.urns(SRC_ILK, srcPsm).ink
is decreased exactly by the moved amountgem
balance of srcPsm.gemJoin()
is decreased exactly by the moved amountvat.vice()
is unchanged after the spell executionvat.sin(MCD_PAUSE_PROXY)
is unchanged after the spell execution
DssLitePsm
ℹ️ 0xf6e72Db5454dd049d0788e411b06CfAF16853042200
Risk Accepted
or Specification Changed
or Code Corrected
forge verify-bytecode
LITE-PSM-{TOKEN_SYMBOL}-A
(i.e. LITE-PSM-USDC-A
)gem
matches the expected token addressdaiJoin
matches MCD_JOIN_DAI
from the chainlogpocket
matches the pocket address in the Exec Sheetwards(deployer) == 0
)MCD_PAUSE_PROXY
has been authed (i.e. require(WardsLike(LITE_PSM).wards(MCD_PAUSE_PROXY) == 1)
)DssLitePsm
has type(uint256).max
approval to spend gem
on behalf of pocket
DssLitePsmMom
ℹ️ 0x467b32b0407Ad764f56304420Cddaa563bDab425200
DssLitePsmMom.sol
is part of the same report as above, found at chainsecurity.comforge verify-bytecode
owner
MCD_PAUSE_PROXY
is the owner
of the contract (i.e. require(MomLike(MOM).owner() == MCD_PAUSE_PROXY
))LitePsmJob
ℹ️ 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Bedss-cron
_sequencer
matches CRON_SEQUENCER
address from the chainlog_litePsm
matches DssLitePsm
address_rushThreshold
matches the Exec Sheet (it might be named as "fill threshold")_gushThreshold
matches the Exec Sheet (it might be named as "trim threshold")_cutThreshold
matches the Exec Sheet (it might be named as "chug threshold")dependencies
checksdependencies
folderdependencies
folderdependencies
folderdependencies
folderDssLitePsm
:buf
is set to the value specified in the Exec Sheetvow
is set to MCD_VOW
from the chainlogMCD_PAUSE_PROXY
is whitelisted to execute swaps with no fees (i.e. KissLike(LITE_PSM).kiss(MCD_PAUSE_PROXY)
)DssLitePsmMom
is authed (i.e. RelyLike(LITE_PSM).rely(MOM)
)DssLitePsmMom
:MCD_ADM
) is set as the authority
(i.e. MomLike(MOM).setAuthority(MCD_ADM)
)LitePsmJob
:CRON_SEQUENCER
MCD_VAT
: new ilk is initializedMCD_JUG
: new ilk is initializedMCD_SPOT
:par
) current value is 1 (1 * RAY
)
ℹ️ Checked on etherscanmat
) is set to 100% (1 * WAD
) for the ilk
:warning: Collateralization ratio (mat
) is indeed set to 100% inside DssLitePsmInit.sol, but that equals to 1 * RAY
, not 1 * WAD
. This checklist instruction need to be fixed after this spellpip
is being used:pip
is set for the ilkpip
is a DSValue
instancepip
is set to 1 (1 * WAD
)pip
deployer is no longer the owner
MCD_PAUSE_PROXY
is the owner
on pip
pip
:
pip
is set for the ilkpip
in the chainlog matches gem
symbol (i.e. PIP_USDC
for USDC
)ILK_REGISTRY
: new ilk is added to the registryCHAINLOG
:DssLitePsm
is added to the chainlog and addresses_mainnet.sol
according to the Exec Sheetpocket
is added to the chainlog and addresses_mainnet.sol
according to the Exec SheetDssLitePsmMom
is added to the chainlog and addresses_mainnet.sol
according to the Exec SheetLitePsmJob
is added to the chainlog and addresses_mainnet.sol
according to the Exec Sheetpip
is being added, it is added to the chainlog and addresses_mainnet.sol
as PIP_{TOKEN_SYMBOL}
(i.e. PIP_USDC
)DssLitePsm
:vow
is set to MCD_VOW
buf
matches the Exec SheetMCD_PAUSE_PROXY
is whitelisted to execute swaps with no fees (i.e. KissLike(LITE_PSM).bud(MCD_PAUSE_PROXY) == 1
)DssLitePsmMom
is authed (i.e. WardsLike(LITE_PSM).wards(MOM) == 1
)buyGem
works as expectedsellGem
works as expectedbuyGemNoFee
works as expectedsellGemNoFee
works as expectedDssLitePsmMom
:MCD_ADM
) is set as the authority
(i.e. MomLike(MOM).authority() == MCD_ADM
)halt
works as expectedLitePsmJob
:CRON_SEQUENCER
(i.e.: SequencerLike(CRON_SEQUENCER).hasJob(LITE_PSM_JOB) == true
)_sequencer
matches CRON_SEQUENCER
address from the chainlog_litePsm
matches DssLitePsm
address_rushThreshold
matches the Exec Sheet (it might be named as "fill threshold")_gushThreshold
matches the Exec Sheet (it might be named as "trim threshold")_cutThreshold
matches the Exec Sheet (it might be named as "chug threshold")workable
returns the correct value:rush() > 0
, returns (true, litePsm.fill.selector)
ℹ️ The test should actually check if workable returns true only for rush() >= rushThreshold
, not 0 (otherwise this job will be very expensive, requiring refill after every transaction)cut() > 0
, returns (true, litePsm.chug.selector)
ℹ️ Same as above (incorrect checklist item)gush() > 0
, returns (true, litePsm.trim.selector)
ℹ️ Same as above (incorrect checklist item)(false, "")
work
has the desired effect:rush() > 0
, fill
is called
ℹ️ Same as above (incorrect checklist item)cut() > 0
, chug
is called
ℹ️ Same as above (incorrect checklist item)gush() > 0
, trim
is called
ℹ️ Same as above (incorrect checklist item)MCD_VAT
: urns[ilk][LITE_PSM].ink
is set to the max value that will not cause an overflow (int256(type(uint256).max / RAY)
)MCD_JUG
: Stability fee (duty
) is set to 0% (1 * RAY
) for the ilk (:information_source: covered in config.sol
)
ℹ️ This is done automatically inside jug.init functionMCD_SPOT
:
spotter(DST_ILK).mat
is set to 100% (1 * RAY
) (:information_source: covered in config.sol
)spotter(DST_ILK).pip
is set correctlyCHAINLOG
: version is bumped: {x}.{y}.{z+1}
(:information_source: covered in config.sol
)ILK_REGISTRY
:
name
matches gem
namesymbol
matches gem
symbolclass
for join-less ilks is used (REG_CLASS = 6
)gem
matches the configured gempip
matches the configured pipgemJoin
is set to address(0)
clip
is set to address(0)
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 Sheetilk
) 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 Sheet 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 SheetDAI
surplus buffer transfers are presentaddresses_wallets.sol
testDAIPayments
testtestDAIPayments
matches number in the Exec SheetMKR
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 Sheetusr
(Vest recipient address) matches Exec Sheetusr
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 Sheetether
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 Sheettau
is expressed as bgn - fin
(i.e. MONTH_DD_YYYY - MONTH_DD_YYYY
)fin
(Vest end timestamp) matches Exec Sheeteta
(Vest cliff duration) matches the following logiceta
is explicitly specified in the Exec Sheet, then the values matcheta
and clf
(Cliff end timestamp) are not specified in the Exec Sheet, 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 Sheet, matches the value, OTHERWISE matches address(0)
cap
) is enough for the new streamstot
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
:warning: This is no longer required after the refactoring PR was merged: https://github.com/makerdao/spells-mainnet/pull/374. Now testChainlogIntegrity
and testChainlogValues
ensures that chainlog values matches addresses defined in the addresses_mainnet.sol
, that version was bumped and that number of keys matches configpublic
/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
modifiertestLitePSMs
testGeneral
(using afterSpell.collaterals["PSM-USDC-A"]
)testGeneral
(using afterSpell.collaterals["LITE-PSM-USDC-A"]
)testGeneral
(using afterSpell.lite_psm_mom_authority
)test_LITE_PSM_USDC_A_MigrationPhase1
testGeneral
(using afterSpell.pause_delay
)testGeneral
(using afterSpell.esm_min
)testEsmAuth
test_CRON_LITE_PSM_JOB
testChainlogIntegrity
and testChainlogValues
test_LITE_PSM_USDC_A_JAR
testSparkSpellIsExecuted
printenv | grep "FOUNDRY_\|DAPP_"
)make test
[PASS]
prefix../scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x8De6DDbCd5053d32292AAA0D2105A32d108484a6
[⠊] Compiling...
[⠢] Compiling 1 files with Solc 0.8.16
[⠰] Solc 0.8.16 finished in 2.24s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 2303300)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 6.69s (5.87s CPU time)
Ran 37 tests for src/DssSpell.t.sol:DssSpellTest
[SKIP] testBytecodeMatches() (gas: 0)
[PASS] testCastCost() (gas: 2160454)
[PASS] testCastOnTime() (gas: 2157350)
[PASS] testChainlogIntegrity() (gas: 7131191)
[PASS] testChainlogValues() (gas: 10607530)
[SKIP] testCollateralIntegrations() (gas: 0)
[PASS] testContractSize() (gas: 11184)
[SKIP] testDAIPayments() (gas: 0)
[SKIP] testDaoResolutions() (gas: 0)
[PASS] testDeployCost() (gas: 5551268)
[PASS] testEsmAuth() (gas: 2170122)
[PASS] testGeneral() (gas: 31958250)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[PASS] testLitePSMs() (gas: 3031367)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 446524)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 496171)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 3386245)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17618)
[PASS] testSparkSpellIsExecuted() (gas: 2163267)
[PASS] testUseEta() (gas: 352708)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
[PASS] test_CRON_LITE_PSM_JOB() (gas: 3330084)
[PASS] test_LITE_PSM_USDC_A_JAR() (gas: 2338463)
[PASS] test_LITE_PSM_USDC_A_MigrationPhase1() (gas: 2206918)
Suite result: ok. 18 passed; 0 failed; 19 skipped; finished in 60.61s (129.54s CPU time)
Ran 2 test suites in 60.89s (67.30s CPU time): 20 tests passed, 0 failed, 19 skipped (39 total tests)
makerdao/community
GitHub repo
ℹ️ https://github.com/makerdao/community/blob/master/governance/votes/Executive%20vote%20-%20July%2025%2C%202024.mdExecutive 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
:warning: Script fails with date: illegal option -- d
, but the hash is generated with the command belowcast keccak -- "$(curl '$URL' -o - 2>/dev/null)"
Insert your Exec Doc Hash here
0x434004820168dfce595861581ed0cf22f2e36fafb236b59a3d6019c78751be14keccak
hash of the empty string (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
)Preparation
[x] Exec Sheet for the specified date is found in the "Executive Vote Implementation Process" google sheet Insert URL to the specific sheet here https://docs.google.com/spreadsheets/d/1w_z5WpqxzwreCcaveB2Ye1PP5B8QAHDglzyxKHG3CHw/edit?gid=1058457016#gid=1058457016
[x] Using Exec Sheet URL from the above, read spell instructions from the Exec Sheet and list them below List all instructions announced in the Exec Sheet
[x] LITE-PSM-USDC-A Phase 1
buf: Set to 20M
[x] Update PSM-USDC-A DC-IAM
[x] Set up LITE-PSM-USDC-A DC-IAM
[x] Add GSM Delay Exception
[x] Initial USDC Migration from PSM-USDC-A to LitePSM
[x] GSM Delay Update
[x] Emergency Shutdown Module Minimum Threshold Update
[x] Add LitePSM keeper network job
[x] Chainlog additions
[x] Spark Spell
Base checks
0.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
)Spell description
TARGET_DATE MakerDAO Executive Spell | Hash: EXEC_DOC_HASH
TARGET_DATE
in the description matches the target date// Hash: cast keccak -- "$(wget 'EXEC_DOC_URL' -q -O - 2>/dev/null)"
Comments inside the spell
// ----- 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/
Dependency checks
foundryup
rm -rf ./lib && git submodule update --init --recursive
Insert checked out submodule paths here
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
IF interfaces are present in the spell
dss-interfaces
dss-interfaces
import "dss-interfaces/dss/VatAbstract.sol";
)
ℹ️ Not done, but not critical!dss-interfaces
, OTHERWISE should be imported from therecast interface <contract_address>
commandLike
suffix (e.g. VatLike
)
IF variable declarations are present in the spell
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
IF new contract is present in the spell (not yet on chainlog or new to chainlog)
GNU AGPLv3
licensevat
, dai
, dog
, ...)wards
or access control
PAUSE_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
)
ℹ️ Not critical, out of scope!Rely
events except for PAUSE_PROXY
and MCD_ESM
(using a block explorer like etherscan)code --diff etherscan.sol github.sol
)addresses_deployers.sol
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 pausedenyProxy
)~~Rely
events except for PAUSE_PROXY
and MCD_ESM
(using a block explorer like etherscan)code --diff etherscan.sol github.sol
)addresses_deployers.sol
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
GNU AGPLv3
licensevat
, dai
, dog
, ...)wards
or access control
PAUSE_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
)
ℹ️ Done in spell, using DssExecLib.authorize
Rely
events except for PAUSE_PROXY
and MCD_ESM
(using a block explorer like etherscan)code --diff etherscan.sol github.sol
)addresses_deployers.sol
GNU AGPLv3
licensevat
, dai
, dog
, ...)wards
or access control
PAUSE_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
IF core system parameter changes are present in the instructions
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 usedIF debt ceiling changes are present in the instructions
ilk
) 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)
IF onboarding is present
IF PSM migration, onboarding or offboarding is present:
dstWant
) matches the Exec SheetsrcKeep
) matches the Exec Sheettin
matches the value in the Exec Sheettout
matches the value in the Exec SheetAutoLine
is updated according to the Exec Sheettin
matches the value in the Exec Sheettout
matches the value in the Exec SheetAutoLine
is updated according to the Exec Sheetbuf
matches the value in the Exec Sheetfill
is called conditionally (if(rush() > 0)
) to ensure liquidity is immediately available after spell executionvat.urns(DST_ILK, dstPsm).art
is increased at least by the moved amountgem
balance of dstPocket
is increased exactly by the moved amountdstPsm
is equal to dstBuf
, UNLESS limited by the debt ceiling (line
)vat.urns(SRC_ILK, srcPsm).art
is decreased exactly by the moved amountvat.urns(SRC_ILK, srcPsm).ink
is decreased exactly by the moved amountgem
balance of srcPsm.gemJoin()
is decreased exactly by the moved amountvat.vice()
is unchanged after the spell executionvat.sin(MCD_PAUSE_PROXY)
is unchanged after the spell executionDssLitePsm
200
forge verify-bytecode
ℹ️ Done manuallyLITE-PSM-{TOKEN_SYMBOL}-A
(i.e. LITE-PSM-USDC-A
)gem
matches the expected token addressdaiJoin
matches MCD_JOIN_DAI
from the chainlogpocket
matches the pocket address in the Exec Sheetwards(deployer) == 0
)MCD_PAUSE_PROXY
has been authed (i.e. require(WardsLike(LITE_PSM).wards(MCD_PAUSE_PROXY) == 1)
)DssLitePsm
has type(uint256).max
approval to spend gem
on behalf of pocket
DssLitePsmMom
200
forge verify-bytecode
ℹ️ Done manuallyowner
MCD_PAUSE_PROXY
is the owner
of the contract (i.e. require(MomLike(MOM).owner() == MCD_PAUSE_PROXY
))LitePsmJob
dss-cron
_sequencer
matches CRON_SEQUENCER
address from the chainlog_litePsm
matches DssLitePsm
address_rushThreshold
matches the Exec Sheet (it might be named as "fill threshold")_gushThreshold
matches the Exec Sheet (it might be named as "trim threshold")_cutThreshold
matches the Exec Sheet (it might be named as "chug threshold")DssLitePsm
:
buf
is set to the value specified in the Exec Sheetvow
is set to MCD_VOW
from the chainlogMCD_PAUSE_PROXY
is whitelisted to execute swaps with no fees (i.e. KissLike(LITE_PSM).kiss(MCD_PAUSE_PROXY)
)DssLitePsmMom
is authed (i.e. RelyLike(LITE_PSM).rely(MOM)
)DssLitePsmMom
:
MCD_ADM
) is set as the authority
(i.e. MomLike(MOM).setAuthority(MCD_ADM)
)LitePsmJob
:
CRON_SEQUENCER
MCD_VAT
: new ilk is initializedMCD_JUG
: new ilk is initializedMCD_SPOT
:
par
) current value is 1 (1 * RAY
)mat
) is set to 100% (1 * WAD
) for the ilk
ℹ️ Set to 1 * RAY which the correct value, the checklist is outdated and will be correctedpip
is being used:pip
is set for the ilkpip
is a DSValue
instancepip
is set to 1 (1 * WAD
)pip
deployer is no longer the owner
MCD_PAUSE_PROXY
is the owner
on pip
pip
:
pip
is set for the ilkpip
in the chainlog matches gem
symbol (i.e. PIP_USDC
for USDC
)ILK_REGISTRY
: new ilk is added to the registryCHAINLOG
:
DssLitePsm
is added to the chainlog and addresses_mainnet.sol
according to the Exec Sheetpocket
is added to the chainlog and addresses_mainnet.sol
according to the Exec SheetDssLitePsmMom
is added to the chainlog and addresses_mainnet.sol
according to the Exec SheetLitePsmJob
is added to the chainlog and addresses_mainnet.sol
according to the Exec Sheetpip
is being added, it is added to the chainlog and addresses_mainnet.sol
as PIP_{TOKEN_SYMBOL}
(i.e. PIP_USDC
)DssLitePsm
:
vow
is set to MCD_VOW
buf
matches the Exec SheetMCD_PAUSE_PROXY
is whitelisted to execute swaps with no fees (i.e. KissLike(LITE_PSM).bud(MCD_PAUSE_PROXY) == 1
)DssLitePsmMom
is authed (i.e. WardsLike(LITE_PSM).wards(MOM) == 1
)buyGem
works as expectedsellGem
works as expectedbuyGemNoFee
works as expectedsellGemNoFee
works as expectedDssLitePsmMom
:
MCD_ADM
) is set as the authority
(i.e. MomLike(MOM).authority() == MCD_ADM
)halt
works as expectedLitePsmJob
:
CRON_SEQUENCER
(i.e.: SequencerLike(CRON_SEQUENCER).hasJob(LITE_PSM_JOB) == true
)_sequencer
matches CRON_SEQUENCER
address from the chainlog_litePsm
matches DssLitePsm
address_rushThreshold
matches the Exec Sheet (it might be named as "fill threshold")_gushThreshold
matches the Exec Sheet (it might be named as "trim threshold")_cutThreshold
matches the Exec Sheet (it might be named as "chug threshold")workable
returns the correct value:
rush() > 0
, returns (true, litePsm.fill.selector)
cut() > 0
, returns (true, litePsm.chug.selector)
gush() > 0
, returns (true, litePsm.trim.selector)
(false, "")
work
has the desired effect:
rush() > 0
, fill
is calledcut() > 0
, chug
is calledgush() > 0
, trim
is calledMCD_VAT
: urns[ilk][LITE_PSM].ink
is set to the max value that will not cause an overflow (int256(type(uint256).max / RAY)
)MCD_JUG
: Stability fee (duty
) is set to 0% (1 * RAY
) for the ilk (:information_source: covered in config.sol
)MCD_SPOT
:
spotter(DST_ILK).mat
is set to 100% (1 * RAY
) (:information_source: covered in config.sol
)spotter(DST_ILK).pip
is set correctly CHAINLOG
: version is bumped: {x}.{y}.{z+1}
(:information_source: covered in config.sol
)ILK_REGISTRY
:
name
matches gem
namesymbol
matches gem
symbolclass
for join-less ilks is used (REG_CLASS = 6
)gem
matches the configured gempip
matches the configured pipgemJoin
is set to address(0)
clip
is set to address(0)
## PSM Off-boarding Checklist
AutoLine
line
is set to 0
ink
for the PSM is set to 0 on MCD_VAT
after execution, UNLESS there has been a donationLine
is adjusted accordinglyILK_REGISTRY
Psm
, GemJoin
and others, as applicable) are being removed from the chainlog{x}.{y+1}.0
Psm
, GemJoin
and others, as applicable) are being scuttledMCD_PAUSE_PROXY
is de-authed from all applicable contractsIF collateral offboarding is present in the spell
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
helperIF RWA updates are present
doc
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 Sheetilk
) 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 Sheet 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)IF payments are present in the spell
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 SheetDAI
surplus buffer transfers are present~~addresses_wallets.sol
testDAIPayments
testtestDAIPayments
matches number in the Exec SheetMKR
or DAI
streams (DssVest
) are created~~VestAbstract
interface is imported from dss-interfaces/dss/VestAbstract.sol
restrict
is used for each stream, UNLESS otherwise explicitly stated in the Exec Sheetusr
(Vest recipient address) matches Exec Sheetusr
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 Sheetether
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 Sheettau
is expressed as bgn - fin
(i.e. MONTH_DD_YYYY - MONTH_DD_YYYY
)fin
(Vest end timestamp) matches Exec Sheeteta
(Vest cliff duration) matches the following logiceta
is explicitly specified in the Exec Sheet, then the values matcheta
and clf
(Cliff end timestamp) are not specified in the Exec Sheet, 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 Sheet, matches the value, OTHERWISE matches address(0)
cap
) is enough for the new streamstot
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 spell
total
(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
IF SubDAO-related content is present
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)IF external contracts calls are present (Not SubDAOs, e.g. Starknet)
delegatecall
CREATE2
(e.g. if it looks like a vanity address) do not have selfdestruct
in their codeIF spell interacts with ChainLog
addresses_mainnet.sol
testNewOrUpdatedChainlogValues
ℹ️ This is not true, the test code has been refactored and tested by different functions, test coverage below![x] Ensure every spell variable is declared as public
/internal
[x] Ensure 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)Tests
DssExecLib.address
file is not being modified by the spell PRpublic
skipped
modifier; OTHERWISE, it MUST have the skipped
modifiertestLitePSMs()
[x] Update PSM-USDC-A DC-IAM, Set up LITE-PSM-USDC-A DC-IAM & Add GSM Delay Exception
✅ testGeneral()
and editing config.sol
properly
[x] Phase 1 USDC Migration from PSM-USDC-A to LitePSM
✅ test_LITE_PSM_USDC_A_MigrationPhase1()
[x] GSM Delay Update & Emergency Shutdown Module Minimum Threshold Update
✅ testGeneral()
and editing config.sol
properly
[x] ESM Authorizations
✅ testEsmAuth()
[x] Add LitePSM keeper network job
✅ test_CRON_LITE_PSM_JOB()
[x] Chainlog additions
✅ testChainlogIntegrity()
& testChainlogValues()
[x] Spark Spell
✅ testSparkSpellIsExecuted()
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 Solc 0.8.16
[⠔] Solc 0.8.16 finished in 1.38s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 2303300)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 49.78s (43.92s CPU time)
Ran 37 tests for src/DssSpell.t.sol:DssSpellTest
[SKIP] testBytecodeMatches() (gas: 0)
[PASS] testCastCost() (gas: 2160542)
[PASS] testCastOnTime() (gas: 2157328)
[PASS] testChainlogIntegrity() (gas: 7131169)
[PASS] testChainlogValues() (gas: 10607508)
[SKIP] testCollateralIntegrations() (gas: 0)
[PASS] testContractSize() (gas: 11162)
[SKIP] testDAIPayments() (gas: 0)
[SKIP] testDaoResolutions() (gas: 0)
[PASS] testDeployCost() (gas: 5551246)
[PASS] testEsmAuth() (gas: 2170122)
[PASS] testGeneral() (gas: 31958250)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[PASS] testLitePSMs() (gas: 3031345)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 446524)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 496149)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 3386333)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17618)
[PASS] testSparkSpellIsExecuted() (gas: 2163267)
[PASS] testUseEta() (gas: 352708)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
[PASS] test_LITE_PSM_USDC_A_CronJob() (gas: 2896623)
[PASS] test_LITE_PSM_USDC_A_JAR() (gas: 2338463)
[PASS] test_LITE_PSM_USDC_A_MigrationPhase1() (gas: 2206918)
Suite result: ok. 18 passed; 0 failed; 19 skipped; finished in 475.11s (1286.59s CPU time)
Ran 2 test suites in 475.71s (524.89s CPU time): 20 tests passed, 0 failed, 19 skipped (39 total tests)
UPDATE: the tests above were run on the wrong commit, the ones below are run on the appropriate one
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x8De6DDbCd5053d32292AAA0D2105A32d108484a6
[⠊] Compiling...
[⠰] Compiling 4 files with Solc 0.8.16
[⠔] Solc 0.8.16 finished in 1.38s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 2303387)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 48.53s (42.61s CPU time)
Ran 37 tests for src/DssSpell.t.sol:DssSpellTest
[SKIP] testBytecodeMatches() (gas: 0)
[PASS] testCastCost() (gas: 2160541)
[PASS] testCastOnTime() (gas: 2157437)
[PASS] testChainlogIntegrity() (gas: 7131278)
[PASS] testChainlogValues() (gas: 10607617)
[SKIP] testCollateralIntegrations() (gas: 0)
[PASS] testContractSize() (gas: 11184)
[SKIP] testDAIPayments() (gas: 0)
[SKIP] testDaoResolutions() (gas: 0)
[PASS] testDeployCost() (gas: 5551268)
[PASS] testEsmAuth() (gas: 2170209)
[PASS] testGeneral() (gas: 31958337)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[PASS] testLitePSMs() (gas: 3031454)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 446524)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 495577)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 3386332)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17618)
[PASS] testSparkSpellIsExecuted() (gas: 2163354)
[PASS] testUseEta() (gas: 352708)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
[PASS] test_CRON_LITE_PSM_JOB() (gas: 3330171)
[PASS] test_LITE_PSM_USDC_A_JAR() (gas: 2338550)
[PASS] test_LITE_PSM_USDC_A_MigrationPhase1() (gas: 2207005)
Suite result: ok. 18 passed; 0 failed; 19 skipped; finished in 474.52s (1204.93s CPU time)
Ran 2 test suites in 475.39s (523.05s CPU time): 20 tests passed, 0 failed, 19 skipped (39 total tests)
Exec Doc checks
[x] Exec Doc for the specified date is found in the makerdao/community
GitHub repo
[x] Exec Doc file name follows the format Executive vote - Month DD, YYYY.md
[x] Extract permanent URL to the raw markdown file and paste it below Insert your Raw Exec Doc URL here https://raw.githubusercontent.com/makerdao/community/7dea36a997198c0b4348e8ca9e37dcb896785cd0/governance/votes/Executive%20vote%20-%20July%2025%2C%202024.md
[ ] Using Exec Doc URL from the above and the TARGET_DATE
, generate Exec Doc Hash via make exec-hash date=$TARGET_DATE $URL
ℹ️ The script is not working locally
Insert your Exec Doc Hash here
[x] Using Exec Doc URL from the above, generate Exec Doc Hash via cast keccak -- "$(curl '$URL' -o - 2>/dev/null)"
Insert your Exec Doc Hash here
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
0x434004820168dfce595861581ed0cf22f2e36fafb236b59a3d6019c78751be14
[x] Make sure that hash above doesn't match keccak
hash of the empty string (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
)
[x] Using Exec Doc URL from the above, read spell instructions from the Exec Doc and list them below List all instructions announced in the Exec Doc
LitePSM Facility Onboarding
- Onboard MCD_LITE_PSM_USDC_A at 0xf6e72Db5454dd049d0788e411b06CfAF16853042.
- Onboard MCD_LITE_PSM_USDC_A_POCKET at 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341.
- Set LitePSM Fixed-sized Amount of Pre-minted Dai (buf) to 20 million DAI.
PSM-USDC-A DC-IAM Parameters Update
LITE-PSM-USDC-A DC-IAM Setup
LITE_PSM_MOM GSM Delay Exception Activation
USDC Migration from PSM-USDC-A to LITE-PSM-USDC-A
GSM Pause Delay Update
ESM Minimum Threshold Update The ESM Minimum Threshold will be increased by 150,000 MKR from 150,000 MKR to 300,000 MKR.
ESM Authorization
LitePSM Keeper Network Job Addition
a keeper network job for calling permissionless LitePSM functions will be activated at 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be with the following parameters:
Chainlog Additions
Spark Proxy Spell -Spark Proxy Spell will be triggered at 0x18427dB17D3113309a0406284aC738f4E649613B. This proxy spell will take the following action:
[x] Office hours value in the Exec Doc matches the spell
[ ] Sum of all payments in the Exec Doc matches the tests
[x] Exec Doc URL in the spell comment matches your Raw Exec Doc URL above
[x] Exec Doc URL in the spell comment refers to the https://github.com/makerdao/community repository
[x] Every action present in the spell code is present in the Exec Doc
[x] Every action in the Exec Doc is present in the spell code
dapptools
)
.sethrc
)export ETH_PASSWORD=~/.env/password.txt
export ETH_KEYSTORE=~/.ethereum/keystore
export ETH_FROM=<address>
make estimate
to estimate gasexport ETH_GAS=X
with the output of the command above + a safety margin (e.g. export ETH_GAS=6_000_000
)seth gas-price
and set ETH_GAS_PRICE
accordingly (e.g. 50 gwei
)gwei
, 50 gwei
could be set)export ETH_GAS_PRICE=$(seth --to-wei X gwei)
(e.g. export ETH_GAS_PRICE=25_000_000_000
)ETH_PRIO_FEE
accordinglyexport ETH_PRIO_FEE=$(seth --to-wei X gwei)
(e.g. export ETH_PRIO_FEE=2_000_000_000
)export ETH_RPC_URL=<url>
to set mainnet RPC URLexport ETHERSCAN_API_KEY=<key>
to set Etherscan API KEYsource .sethrc
to make env vars availableseth ls
seth chain
make deploy
src/test/config.sol
is edited correctlydeployed_spell: address(<deployed_spell_address>)
deployed_spell_created: <timestamp>
deployed_spell_block: <block number>
make deploy-info tx=<tx_hash>
add deployed spell info
commitmake cast-on-tenderly spell=0x...
commandpublic explorer url
is publicly accessible (e.g. using incognito browser mode)
:white_check_mark: https://dashboard.tenderly.co/explorer/vnet/b2e40858-22de-4b53-8f64-9d31ac604f2acast-on-tenderly
command is executed several times for the same spell, delete all testnets of the same name except the last onemake archive-spell
for the current date (or make archive-spell date="YYYY-MM-DD"
) using Target Date inside the Exec DocTLDR: 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)
ℹ️ Verified code exactly matches forge flatten src/DssSpell.sol -o out/flat.sol
outputmake check-deployed-spell
ℹ️ The script initially failed with jq: error (at <stdin>:0): Cannot index string with number
. Fixed by adding &apikey=$ETHERSCAN_API_KEY"
on line 43 (due to etherscan API change)DssExecLib.address
filedeployed_spell_created
matches deployment timestamp
:warning: The output of the script states that it's incorrect, but they are correct if checked manually below. This is a known problem with the scriptdeployed_spell_block
matches deployment block number
:warning: As abovemake 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 Releasec0d3c6c
made on Feb 1, 2022, while git submodule lib/dss-exec-lib
is set to track the latest commit 69b658f
made on Jan 23, 2023. Here is the diff between the latest release and the submodule: https://github.com/makerdao/dss-exec-lib/compare/v0.0.9...69b658f35d8618272cd139dfc18c5713caf6b96b#diff-72201ff20380f5c7fc89281be3ad2dd6bd5a992f246d41d6d9d97f71e078d40d. The only major difference between deployed and the imported library is the new setRWAIlkDebtCeiling
, which we're not using in this particular spellmake 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 Solc 0.8.16
[⠰] Solc 0.8.16 finished in 2.26s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 2303387)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 5.68s (5.21s CPU time)
Ran 37 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 5574786)
[PASS] testCastCost() (gas: 2160541)
[PASS] testCastOnTime() (gas: 2157437)
[PASS] testChainlogIntegrity() (gas: 7131278)
[PASS] testChainlogValues() (gas: 10607617)
[SKIP] testCollateralIntegrations() (gas: 0)
[SKIP] testContractSize() (gas: 0)
[SKIP] testDAIPayments() (gas: 0)
[SKIP] testDaoResolutions() (gas: 0)
[SKIP] testDeployCost() (gas: 0)
[PASS] testEsmAuth() (gas: 2170209)
[PASS] testGeneral() (gas: 31960434)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[PASS] testLitePSMs() (gas: 3031454)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 446524)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 495577)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 3386332)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17618)
[PASS] testSparkSpellIsExecuted() (gas: 2163354)
[PASS] testUseEta() (gas: 352708)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
[PASS] test_CRON_LITE_PSM_JOB() (gas: 3323159)
[PASS] test_LITE_PSM_USDC_A_JAR() (gas: 2338550)
[PASS] test_LITE_PSM_USDC_A_MigrationPhase1() (gas: 2207005)
Suite result: ok. 17 passed; 0 failed; 20 skipped; finished in 51.64s (120.87s CPU time)
Ran 2 test suites in 51.94s (57.32s CPU time): 19 tests passed, 0 failed, 20 skipped (39 total tests)
testBytecodeMatches
passdelegatecall
code inside verified codeselfdestruct
code present in the deployed codefalse
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
⚠️ The script gives a wrong result locally, checked manually belowdeployed_spell_block
matches deployment block number
⚠️ The script gives a wrong result locally, checked manually belowmake deploy-info tx=<tx>
matches config
ℹ️ tx=0xc9923d961f228ab78deb565287664615b13f0f53431873bd8ac582710b1b3f45
deployed_spell_created
timestamp
ℹ️ timestamp: 1721926643deployed_spell_block
block number
ℹ️ block: 20384902DssExecLib.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 Solc 0.8.16
[⠒] Solc 0.8.16 finished in 1.42s
Compiler run successful!
Ran 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 2303352)
[PASS] testStarknetSpell() (gas: 2324)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 48.42s (44.73s CPU time)
Ran 37 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 5574786)
[PASS] testCastCost() (gas: 2160506)
[PASS] testCastOnTime() (gas: 2157402)
[PASS] testChainlogIntegrity() (gas: 7131243)
[PASS] testChainlogValues() (gas: 10607582)
[SKIP] testCollateralIntegrations() (gas: 0)
[SKIP] testContractSize() (gas: 0)
[SKIP] testDAIPayments() (gas: 0)
[SKIP] testDaoResolutions() (gas: 0)
[SKIP] testDeployCost() (gas: 0)
[PASS] testEsmAuth() (gas: 2170174)
[PASS] testGeneral() (gas: 31960399)
[SKIP] testIlkClipper() (gas: 0)
[SKIP] testL2ArbitrumSpell() (gas: 0)
[SKIP] testL2OptimismSpell() (gas: 0)
[SKIP] testLerpSurplusBuffer() (gas: 0)
[PASS] testLitePSMs() (gas: 3031419)
[SKIP] testMKRPayments() (gas: 0)
[SKIP] testMedianizers() (gas: 0)
[SKIP] testNewIlkRegistryValues() (gas: 0)
[PASS] testNextCastTime() (gas: 446524)
[SKIP] testOSMs() (gas: 0)
[SKIP] testOffboardings() (gas: 0)
[PASS] testOfficeHours() (gas: 494862)
[SKIP] testOracleList() (gas: 0)
[PASS] testPSMs() (gas: 3386297)
[SKIP] testRemoveChainlogValues() (gas: 0)
[PASS] testRevertIfNotScheduled() (gas: 17618)
[PASS] testSparkSpellIsExecuted() (gas: 2163319)
[PASS] testUseEta() (gas: 352708)
[SKIP] testVestDAI() (gas: 0)
[SKIP] testVestMKR() (gas: 0)
[SKIP] testYankDAI() (gas: 0)
[SKIP] testYankMKR() (gas: 0)
[PASS] test_CRON_LITE_PSM_JOB() (gas: 3344160)
[PASS] test_LITE_PSM_USDC_A_JAR() (gas: 2338515)
[PASS] test_LITE_PSM_USDC_A_MigrationPhase1() (gas: 2206970)
Suite result: ok. 17 passed; 0 failed; 20 skipped; finished in 476.99s (1244.52s CPU time)
Ran 2 test suites in 478.21s (525.40s CPU time): 19 tests passed, 0 failed, 20 skipped (39 total tests)
new-spells
is correctnew-spells
channel (via a separate "reply to" message, restating the address to avoid edits)
new-spells
Description
Contribution Checklist
(PE-<TICKET_NUMBER>)
Checklist
officeHours
modifier override30 days
unless otherwise specified)ETH_GAS_LIMIT="XXX" ETH_GAS_PRICE="YYY" make deploy
mainnet
contract on etherscanmake archive-spell
ormake date="YYYY-MM-DD" archive-spell
to make an archive directory and copyDssSpell.sol
,DssSpell.t.sol
,DssSpell.t.base.sol
, andDssSpellCollateralOnboarding.sol
squash and merge
this PR