Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mainnet spell 2024-07-25 #417

Merged
merged 24 commits into from
Jul 25, 2024
Merged

Mainnet spell 2024-07-25 #417

merged 24 commits into from
Jul 25, 2024

Conversation

amusingaxl
Copy link
Contributor

Description

Contribution Checklist

  • PR title starts with (PE-<TICKET_NUMBER>)
  • Code approved
  • Tests approved
  • CI Tests pass

Checklist

  • Every contract variable/method declared as public/external private/internal
  • Consider if this PR needs the officeHours modifier override
  • Verify expiration (30 days unless otherwise specified)
  • Verify hash in the description matches here
  • Validate all addresses used are in changelog or known
  • Notify any external teams affected by the spell so they have the opportunity to review
  • Deploy spell ETH_GAS_LIMIT="XXX" ETH_GAS_PRICE="YYY" make deploy
  • Verify mainnet contract on etherscan
  • Change test to use mainnet spell address and deploy timestamp
  • Run make archive-spell or make date="YYYY-MM-DD" archive-spell to make an archive directory and copy DssSpell.sol, DssSpell.t.sol, DssSpell.t.base.sol, and DssSpellCollateralOnboarding.sol
  • squash and merge this PR

@amusingaxl amusingaxl marked this pull request as ready for review July 22, 2024 20:32
src/DssSpell.sol Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Show resolved Hide resolved
src/DssSpell.sol Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.t.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Show resolved Hide resolved
@SidestreamColdMelon
Copy link
Contributor

SidestreamColdMelon commented Jul 25, 2024

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.

Development Stage

  • Preparation
    • 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
    • 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
      • General settings
        • Office Hours Yes
        • Global Line Modifier No
        • Order of Operations Issues No
        • Total Amount of DAI Transfers 0
        • Total Amount of MKR Transfers 0
      • Content
        • LITE-PSM-USDC-A Onboarding
          • Onboard MCD_LITE_PSM_USDC_A at 0xf6e72Db5454dd049d0788e411b06CfAF16853042
          • Onboard MCD_LITE_PSM_USDC_A_POCKET at 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341
          • Set MCD_LITE_PSM_USDC_A buf to 20M
        • Update PSM-USDC-A DC-IAM
          • Set PSM-USDC-A DC-IAM DC-IAM line: 10B (Unchanged)
          • Set PSM-USDC-A DC-IAM DC-IAM gap: Decrease for 20M from 400M to 380M
          • Set PSM-USDC-A DC-IAM DC-IAM ttl: 12h (Unchanged)
        • Set up LITE-PSM-USDC-A DC-IAM
          • Set LITE-PSM-USDC-A DC-IAM line: Set to 50M
          • Set LITE-PSM-USDC-A DC-IAM gap: Set to 20M
          • Set LITE-PSM-USDC-A DC-IAM ttl: Set to 12h
        • Add GSM Delay Exception
          • Activate LITE_PSM_MOM GSM Delay Exception at 0x467b32b0407Ad764f56304420Cddaa563bDab425
        • Phase 1 USDC Migration from PSM-USDC-A to LitePSM
          • Migrate 20 million USDC from PSM-USDC-A to LITE-PSM-USDC-A
          • Leave at least 200M USDC reserves in PSM-USDC-A
        • GSM Delay Update
          • Decrease the GSM Pause Delay by 14h, from 30h to 16h
        • Emergency Shutdown Module Minimum Threshold Update
          • Increase the ESM (Emergency Shutdown Module) minimum threshold by 150k MKR from 150k MKR to 300k MKR
        • ESM Authorizations
          • Auth ESM on MCD_LITE_PSM_USDC_A_IN_CDT_JAR
        • Add LitePSM keeper network job
          • sequencer.addJob( 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be )
          • fill: Set threshold at 15M DAI
          • trim: Set threshold at 30M DAI
          • chug: Set threshold at 300k DAI
        • Chainlog additions
          • Add 0xf6e72Db5454dd049d0788e411b06CfAF16853042 as MCD_LITE_PSM_USDC_A
          • Add 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341 as MCD_LITE_PSM_USDC_A_POCKET
          • Add 0x69cA348Bd928A158ADe7aa193C133f315803b06e as MCD_LITE_PSM_USDC_A_JAR
          • Add 0x5eeB3D8D60B06a44f6124a84EeE7ec0bB747BE6d as MCD_LITE_PSM_USDC_A_IN_CDT_JAR
          • Add 0x467b32b0407Ad764f56304420Cddaa563bDab425 as LITE_PSM_MOM
          • Add 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be as CRON_LITE_PSM_JOB
        • Spark Spell
          • Trigger Spark Proxy Spell at 0x18427dB17D3113309a0406284aC738f4E649613B
  • Base checks
    • Current solc version 0.8.16
    • Office hours is 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
    • Office hours value matches the Exec Sheet
    • 30 days spell expiry set in the constructor (block.timestamp + 30 days)
  • Spell description
    • Description follows the format TARGET_DATE MakerDAO Executive Spell | Hash: EXEC_DOC_HASH
    • TARGET_DATE in the description matches the target date
    • Accompanying comment above spell description follows the format // Hash: cast keccak -- "$(wget 'EXEC_DOC_URL' -q -O - 2>/dev/null)"
  • Comments inside the spell
    • Every Section text from the Exec Sheet is copied to the spell code as a comment surrounded by the set of dashes (E.g. // ----- Section text -----)
    • Every Instruction text from the Exec Sheet is copied to the spell code as // Instruction text
    • Every Instruction text have newline above it
      ⚠️ This is not always followed, but is a good compromize for readability
    • IF an instruction can not be taken, it should have explanation under the instruction prefixed with // 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:
    • Every proof url from the Exec Sheet, such as Reasoning URL and Authority URL is present in the spell code under relevant section or instruction (depending on which row the url is present)
    • Every proof url from the Exec Sheet, such as 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
    • Update Foundry by running 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)
      
    • Reinstall libraries by running 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'
    • IF submodule upgrades are present, make sure dss-exec-lib is synced as well
    • git submodule hash of dss-exec-lib (run git submodule status) matches the latest release version or newer
    • dss-interfaces library used inside lib/dss-exec-lib matches submodule used inside lib/dss-test
  • IF interfaces are present in the spell
    • Interfaces imported from dss-interfaces
      • No unused dss-interfaces
      • Only single import layout is used (e.g. import "dss-interfaces/dss/VatAbstract.sol";)
    • Static Interfaces
      • No unused static interfaces
      • Declared static interface not present in the dss-interfaces, OTHERWISE should be imported from there
        ⚠️ 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 convention
      • Interface matches deployed contract using cast interface <contract_address> command
        ℹ️ When checked via cast interface command, ProxyLike doesn't match, although matches the source code – a known limitation of the command
      • Interface naming style should match with Like suffix (e.g. VatLike)
      • Each static interface declare only functions actually used in the spell code
  • IF variable declarations are present in the spell
    • IF precision units are present
      • Precision units used in the spell match their defined values:
        • WAD = 10 ** 18
        • RAY = 10 ** 27
        • RAD = 10 ** 45
      • Precision units match with Numerical Ranges
      • Each variable visibility is declared as internal
      • Each variable state mutability is declared as constant
    • IF math units are present
      • Match their defined values:
        • HUNDRED = 10 ** 2
        • THOUSAND = 10 ** 3
        • MILLION = 10 ** 6
        • BILLION = 10 ** 9
      • Match with config
      • Each variable visibility is declared as internal
      • Each variable state mutability is declared as constant
    • IF rates are present
      • Rates match generated locally via make rates pct=<pct> (e.g. pct=0.75, for 0.75%)
      • Rates match IPFS document
      • Rate variable name conforms to X_PT_Y_Z_PCT_RATE (e.g. ZERO_PT_SEVEN_FIVE_PCT_RATE for 0.75%)
      • Rate variable visibility declared as internal
      • Rate variable state mutability declared as constant
    • IF timestamps are present
      • Comment above timestamp states full date including UTC timezone
      • Timestamp converts back to the correct date
      • Timestamp converts back to the UTC timezone
      • Variable naming matches MMM_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 as internal
      • Each variable state mutability is declared as constant
  • IF new contract is present in the spell (not yet on chainlog or new to chainlog)
    • 0xf6e72Db5454dd049d0788e411b06CfAF16853042 named as MCD_LITE_PSM_USDC_A
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
        ℹ️
        • ilk_ (bytes32): 0x4c4954452d50534d2d555344432d410000000000000000000000000000000000
          • Bytes32-encoded string LITE-PSM-USDC-A (matches exec sheet)
        • gem_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
          • Matches USDC address in the chainlog
        • daiJoin_ (address): 0x9759A6Ac90977b93B58547b4A71c78317f391A28
          • Matches MCD_JOIN_DAI address in the chainlog
        • pocket_ (address): 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341
          • Matches MCD_LITE_PSM_USDC_A_POCKET address in the spell (see below)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
          ⚠️ 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 address
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode 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)
      • Deployer address is included into addresses_deployers.sol
    • 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341 named as MCD_LITE_PSM_USDC_A_POCKET
      ℹ️ This address is EOA
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
      • Deployer address is included into addresses_deployers.sol
    • 0x467b32b0407Ad764f56304420Cddaa563bDab425 named as LITE_PSM_MOM
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
        ℹ️ This contract doesn't have constructor parameters
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
          ℹ️ The owner is set to PAUSE_PROXY address
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
          ℹ️ There is only a single owner possible, authority is currently set to address(0)
        • Ensure 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)
          ⚠️ 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 address
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode 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)
      • Deployer address is included into addresses_deployers.sol
    • 0x69cA348Bd928A158ADe7aa193C133f315803b06e named as MCD_LITE_PSM_USDC_A_JAR
      • Source code is verified on etherscan
        ℹ️ Similar Match Source Code on etherscan (due to their limitation), but fully confirmed on sourcify
      • Compilation optimizations match deployment settings defined in the source code repo
        ℹ️ Disabled as in the foundry.toml
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
        ℹ️
        • chainlog_ (address): 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F
          • Matches CHANGELOG address in the chainlog (i.e. the chainlog address itself)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
        ℹ️ Matches, checked manually (due to the verified source code being mutli-file)
      • Deployer address is included into addresses_deployers.sol
    • 0x5eeB3D8D60B06a44f6124a84EeE7ec0bB747BE6d named as MCD_LITE_PSM_USDC_A_IN_CDT_JAR
      • Source code is verified on etherscan
        ℹ️ Similar Match Source Code on etherscan (due to their limitation), but fully confirmed on sourcify
      • Compilation optimizations match deployment settings defined in the source code repo
        ℹ️ Disabled as in the foundry.toml
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
        ℹ️
        • _dai (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
          • Matches MCD_DAI address in the chainlog
        • _gem (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
          • Matches USDC address in the chainlog
        • _psm (address): 0xf6e72Db5454dd049d0788e411b06CfAF16853042
          • Matches MCD_LITE_PSM_USDC_A address onboarded via this spell
        • _to (address): 0x69cA348Bd928A158ADe7aa193C133f315803b06e
          • Matches MCD_LITE_PSM_USDC_A_JAR address onboarded via this spell
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
        ℹ️ Matches, checked manually (due to the verified source code being mutli-file)
      • Deployer address is included into addresses_deployers.sol
    • 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be named as CRON_LITE_PSM_JOB
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
        ℹ️ Enabled as in the foundry.toml
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
        ℹ️
        • _sequencer (address): 0x238b4E35dAed6100C6162fAE4510261f88996EC9
          • Matches CRON_SEQUENCER address in the chainlog
        • _litePsm (address): 0xf6e72Db5454dd049d0788e411b06CfAF16853042
          • Matches MCD_LITE_PSM_USDC_A address onboarded via this spell
        • _rushThreshold (uint256): 15000000000000000000000000
        • _cutThreshold (uint256): 300000000000000000000000
        • _gushThreshold (uint256): 30000000000000000000000000
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
        ℹ️ Matches, checked manually (due to the verified source code being mutli-file)
      • Deployer address is included into addresses_deployers.sol
  • IF core system parameter changes are present in the instructions
    ℹ️ Although not present in this list, several core system paraters are changed in this spell: 1) MCD_PAUSE.delay is set via PauseLike(MCD_PAUSE).setDelay (as no DssExecLib found); 2) MCD_ESM.min is set via DssExecLib.setValue
  • IF debt ceiling changes are present in the instructions
  • IF onboarding is present
  • IF PSM migration, onboarding or offboarding is present:
    • Insert and follow the relevant checklists below:
      • PSM Checklists

        PSM Migration Checklist

        • IF contracts are being on-boarded in the current spell, execute the full LitePSM On-boarding Checklist
        • IF a PSM is deprecated in the migration, execute the full PSM Off-boarding Checklist
        • IF present, max amount of gems to move (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#L35
        • IF present, min amount of gems to keep (srcKeep) 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#L40
        • Source PSM:
          • ilk matches source PSM
            ℹ️ MCD_PSM_USDC_A.gemJoin().gem() == USDC
          • IF present, tin matches the value in the Exec Sheet
          • IF present, tout matches the value in the Exec Sheet
          • AutoLine is updated according to the Exec Sheet
        • Destination PSM:
          • ilk matches destination PSM
            ℹ️ MCD_LITE_PSM_USDC_A.gem() == USDC or MCD_LITE_PSM_USDC_A.gemJoin().gem() == USDC
          • IF present, tin matches the value in the Exec Sheet
          • IF present, tout matches the value in the Exec Sheet
          • AutoLine is updated according to the Exec Sheet
          • buf matches the value in the Exec Sheet
          • fill is called conditionally (if(rush() > 0)) to ensure liquidity is immediately available after spell execution
        • Test coverage:
          • Collateral amount that is fetched from the source PSM matches the collateral is added to the destination PSM
            • vat.urns(DST_ILK, dstPsm).art is increased at least by the moved amount
            • gem balance of dstPocket is increased exactly by the moved amount
            • Dai balance of dstPsm is equal to dstBuf, UNLESS limited by the debt ceiling (line)
            • vat.urns(SRC_ILK, srcPsm).art is decreased exactly by the moved amount
            • vat.urns(SRC_ILK, srcPsm).ink is decreased exactly by the moved amount
            • gem balance of srcPsm.gemJoin() is decreased exactly by the moved amount
          • No bad debt is left behind
            • vat.vice() is unchanged after the spell execution
            • vat.sin(MCD_PAUSE_PROXY) is unchanged after the spell execution

        LitePSM On-boarding Checklist

        • Deployed Contracts
          • DssLitePsm ℹ️ 0xf6e72Db5454dd049d0788e411b06CfAF16853042
            • Optimizer is enabled
            • Optimize runs is set to 200
            • Contract has been reviewed by minimum 2 specialized Active Ecosystem Actors
            • Contract has been audited by an external party
              • Audit report source could be confirmed (i.e. found on auditor's website)
                ℹ️ Found at chainsecurity.com although the PDF itself is uploaded to a CDN
              • All issues found were fixed or acknowledged
                ℹ️ All fundings are marked either as Risk Accepted or Specification Changed or Code Corrected
              • No code changes are done after final audit report, based on the commit hash found in the report +
                ℹ️ Latest audited version is at commit 2f11f4bc47d96f4ebf025a1e4a249987150f9baa
                • EITHER code diff check for each individual file
                • OR bytecode verification tool such as forge verify-bytecode
            • Deployed contract matches the code in the repo
            • Constructor params:
              • ilk is named LITE-PSM-{TOKEN_SYMBOL}-A (i.e. LITE-PSM-USDC-A)
              • gem matches the expected token address
              • daiJoin matches MCD_JOIN_DAI from the chainlog
              • pocket matches the pocket address in the Exec Sheet
            • Deployer no longer has privileged access (wards(deployer) == 0)
            • MCD_PAUSE_PROXY has been authed (i.e. require(WardsLike(LITE_PSM).wards(MCD_PAUSE_PROXY) == 1))
            • Sanity check: DssLitePsm has type(uint256).max approval to spend gem on behalf of pocket
          • DssLitePsmMom ℹ️ 0x467b32b0407Ad764f56304420Cddaa563bDab425
            • Optimizer is enabled
            • Optimize runs is set to 200
            • Contract has been reviewed by minimum 2 specialized Active Ecosystem Actors
            • Contract has been audited by an external party
              • Audit report source could be confirmed (i.e. found on auditor's website)
                ℹ️ DssLitePsmMom.sol is part of the same report as above, found at chainsecurity.com
              • All issues found were fixed or acknowledged
              • No code changes are done after final audit report, based on the commit hash found in the report +
                ℹ️ Latest audited version is at commit 2f11f4bc47d96f4ebf025a1e4a249987150f9baa
                • EITHER code diff check for each individual file
                • OR bytecode verification tool such as forge verify-bytecode
            • Deployed contract matches the code in the repo
            • Deployer is no longer the owner
            • MCD_PAUSE_PROXY is the owner of the contract (i.e. require(MomLike(MOM).owner() == MCD_PAUSE_PROXY))
          • LitePsmJob ℹ️ 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be
            • Uses the default Solidity version in dss-cron
            • Optimizer is enabled
            • Deployed contract matches the code in the repo
            • Constructor params:
              • _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")
          • ℹ️ Additional dependencies checks
        • Initialization
          • DssLitePsm:
            • buf is set to the value specified in the Exec Sheet
            • vow is set to MCD_VOW from the chainlog
            • MCD_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:
            • The chief (MCD_ADM) is set as the authority (i.e. MomLike(MOM).setAuthority(MCD_ADM))
          • LitePsmJob:
            • Job is added to CRON_SEQUENCER
          • MCD_VAT: new ilk is initialized
          • MCD_JUG: new ilk is initialized
          • MCD_SPOT:
            • Sanity check: Dai parity (par) current value is 1 (1 * RAY)
              ℹ️ Checked on etherscan
            • Collateralization ratio (mat) is set to 100% (1 * WAD) for the ilk
              ⚠️ 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 spell
            • IF a new pip is being used:
              • pip is set for the ilk
              • pip is a DSValue instance
              • The value on pip is set to 1 (1 * WAD)
              • pip deployer is no longer the owner
              • MCD_PAUSE_PROXY is the owner on pip
            • OTHERWISE when reusing an existing pip:
              • pip is set for the ilk
              • pip in the chainlog matches gem symbol (i.e. PIP_USDC for USDC)
          • ILK_REGISTRY: new ilk is added to the registry
          • CHAINLOG:
            • DssLitePsm is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
            • pocket is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
            • DssLitePsmMom is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
            • LitePsmJob is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
            • IF a new pip is being added, it is added to the chainlog and addresses_mainnet.sol as PIP_{TOKEN_SYMBOL} (i.e. PIP_USDC)
        • Test coverage:
          • DssLitePsm:
            • vow is set to MCD_VOW
            • buf matches the Exec Sheet
            • MCD_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)
            • E2E tests:
              • buyGem works as expected
              • sellGem works as expected
              • buyGemNoFee works as expected
              • sellGemNoFee works as expected
          • DssLitePsmMom:
            • Chief (MCD_ADM) is set as the authority (i.e. MomLike(MOM).authority() == MCD_ADM)
            • E2E tests:
              • halt works as expected
          • LitePsmJob:
            • Job is added to 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")
            • E2E tests:
              • workable returns the correct value:
                • IF 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)
                • OTHERWISE IF cut() > 0, returns (true, litePsm.chug.selector)
                  ℹ️ Same as above (incorrect checklist item)
                • OTHERWISE IF gush() > 0, returns (true, litePsm.trim.selector)
                  ℹ️ Same as above (incorrect checklist item)
                • OTHERWISE returns (false, "")
              • work has the desired effect:
                • IF rush() > 0, fill is called
                  ℹ️ Same as above (incorrect checklist item)
                • OTHERWISE IF cut() > 0, chug is called
                  ℹ️ Same as above (incorrect checklist item)
                • OTHERWISE IF gush() > 0, trim is called
                  ℹ️ Same as above (incorrect checklist item)
                • OTHERWISE reverts
            • 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 function
            • 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:
              • New ilk is added to the registry
              • name matches gem name
              • symbol matches gem symbol
              • class for join-less ilks is used (REG_CLASS = 6)
              • gem matches the configured gem
              • pip matches the configured pip
              • gemJoin is set to address(0)
              • clip is set to address(0)
  • IF collateral offboarding is present in the spell
    • 1st stage collateral offboarding
      • Collateral type (ilk) is removed from AutoLine (MCD_IAM_AUTO_LINE) IF currently enabled
      • Collateral debt ceiling (vat.ilk.line) is set to 0
      • Global debt ceiling (vat.Line) decreased by the total amount of offboarded ilks
    • 2nd stage collateral offboarding
      • All 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 to 0 IF requested by governance
      • Flat keeper incentive (tip) is set to 0 IF requested by governance
      • Relative keeper incentive (chip) is set to 0 IF requested by governance
      • Max liquidation amount (hole) is adjusted via DssExecLib.setIlkMaxLiquidationAmount(ilk, amount) IF requested by governance
      • Relevant clipper contract (MCD_CLIP_) is active (i.e. stopped is 0)
      • Liquidations are triggered via (depending on governance instruction):
        • EITHER liquidation ratio (spotter.ilk.mat) being set very high in the spell (using DssExecLib.setValue(DssExecLib.spotter(), ilk, "mat", ratio))
        • OR via enabling linear interpolation (DssExecLib.linearInterpolation(name, target, ilk, what, startTime, start, end, duration))
          • Ensure name format matches "XXX-X Offboarding"
          • Ensure target matches DssExecLib.spotter() address
          • Ensure ilk format matches collateral type (ilk) name ("XXX-X")
          • Ensure what matches string "mat"
          • Ensure startTime matches block.timestamp
          • Ensure start uses variable CURRENT_XXX_A_MAT
          • Ensure start matches current spotter.ilk.mat value
          • Ensure end uses variable TARGET_XXX_A_MAT
          • Ensure end value matches the instruction
          • Ensure end allows liquidation of all remaining vaults (end is bigger than collateral_type_collateralization_ratio * risk_multiplier_factor)
          • Ensure duration matches the instruction
      • Spotter price is updated via DssExecLib.updateCollateralPrice(ilk) IF collateral have no running oracle (i.e. relevant PIP_ contract have outdated zzz value)
      • Spotter price is updated after all other actions
      • Offboarding is tested at least via _checkIlkClipper helper
  • IF RWA updates are present
    • IF doc is updated
      • _updateDoc helper is copied one-to-one from the archive and defined above actions
      • _updateDoc(ilk, doc) is called in the spell
    • IF debt ceiling is updated
      • IF AutoLine update is requested by the Exec Sheet
      • IF regular debt ceiling (vat.ilk.line) update is requested by the Exec Sheet
      • Liquidation oracle price is bumped via RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).bump(ilk, val) pattern
        • Comment above bump explains val computation via // Note: the formula is: "debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"
        • Comment above bump provides locally executable formula (e.g. // bc -l <<< 'scale=18; 50000000 * e(l(1.07) * (3342/365)) * 1.00' | cast --to-wei)
          • The formula matches the example provided above
          • debt_ceiling in the executable formula matches new debt ceiling set in the spell or the maximum possible debt ceiling in case of the enabled AutoLine
          • rwa_stability_fee in the executable formula matches stability fee of the specified RWA found on chain
          • minimum_deal_duration_in_years in the executable formula matches number found in the Exec Sheet of the spell containing relevant RWA onboarding
          • liquidation_ratio in the executable formula matches liquidation ratio of the specified RWA found on chain
          • Executing formula locally provides integer number that matches the val in the spell
        • val makes sense in context of the rate mechanism
      • IF multiple RWA ilks are being combined into one, val calculation is done once per ilk and added to make the total, with separate executable formulas provided in comments. The existing val value can be retrieved by calling read() on PIP_RWAXX and converting the result into decimal
      • Oracle price is updated via DssExecLib.updateCollateralPrice(ilk)
      • IF soft liquidation explicitly requested to be triggered (via .tell(ilk)) AND debt ceiling is 0 (OR is being set to 0 in the current spell)
        • RwaLiquidationOracle.tell(ilk) call is present
        • IF RWAXX_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
    • IF MKR transfers are present
      • Recipient address in the instruction is in the checksummed format
      • Recipient address matches Exec Sheet
      • Recipient address variable name matches one found in addresses_wallets.sol
      • Transfer amount matches Exec Sheet
      • Transfer amount is specified with (at least) 2 decimals using ether keyword
      • IF ether 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 via testMKRPayments test
      • Sum of all MKR transfers tested in testMKRPayments matches number in the Exec Sheet
    • IF DAI surplus buffer transfers are present
      • Recipient address in the instruction is in the checksummed format
      • Recipient address matches Exec Sheet
      • Recipient address variable name matches one found in addresses_wallets.sol
      • Transfer amount matches Exec Sheet
      • The transfers are tested via testDAIPayments test
      • Sum of all DAI transfers tested in testDAIPayments matches number in the Exec Sheet
    • IF MKR 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 Sheet
      • usr (Vest recipient address) matches Exec Sheet
      • usr address in the instruction is in the checksummed format
      • usr address variable name match one found in addresses_wallets.sol
      • tot (Total stream amount) matches Exec Sheet
      • IF ether 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 Sheet, account for leap days
      • bgn (Vest start timestamp) matches Exec Sheet
      • tau is expressed as bgn - fin (i.e. MONTH_DD_YYYY - MONTH_DD_YYYY)
      • fin (Vest end timestamp) matches Exec Sheet
      • eta (Vest cliff duration) matches the following logic
        • IF eta is explicitly specified in the Exec Sheet, then the values match
        • IF eta and clf (Cliff end timestamp) are not specified in the Exec Sheet, then eta is 0
        • IF clf is specified, but clf <= bgn, then eta is 0
        • IF clf is specified and clf > bgn, eta is expressed as clf - bgn (i.e. MONTH_DD_YYYY - MONTH_DD_YYYY)
      • IF mgr (Vest manager address) is specified in the Exec Sheet, matches the value, OTHERWISE matches address(0)
      • Ensure that max vesting rate (cap) is enough for the new streams
        • The maximum vesting rate (tot divided by tau) <= the maximum vest streaming rate (cap)
        • The maximum vesting rate (tot divided by tau) > the maximum vest streaming rate (cap)
        • Calculate new 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)
      • IF max vesting rate (cap) is changed in the spell
        • Governance facilitators were notified
        • Exec Sheet contain explicit instruction
        • Exec Sheet contain explicit instruction
      • IF MKR stream (DssVestTransferrable) is present
        • Vest contract's MKR allowance increased by the cumulative total (the sum of all tot values)
        • Ensure allowance increase follows archive patterns
      • Tested via testVestDAI or testVestMKR
    • IF MKR or DAI vest termination (Yank) is present
      • Yanked stream ID matches Exec Sheet
      • MCD_VEST_MKR_TREASURY chainlog address is used for MKR stream yank
      • MCD_VEST_DAI chainlog address is used for DAI stream yank
      • Tested via testYankDAI or testYankMKR
  • IF SubDAO-related content is present
    • IF SubDAO provides SubProxy spell address
      • SubDAO spell address matches Exec Sheet
      • Executed via ProxyLike(SUBDAO_PROXY).exec(SUBDAO_SPELL, abi.encodeWithSignature("execute()"));
      • Execution is NOT delegate call
      • IF SubDAO spell deployer is a smart contract (e.g. multisig or factory), ensure the deployer address is in addresses_deployers.sol as an entry
      • Ensure 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 scripts
        ℹ️ This will be once again checked when the core spell is executed on a Tenderly Testnet. Local traces doesn't seem to indicate any "out of gas" errors
    • IF SubDAO provides instructions to be executed by the main spell (i.e. that will operate within Pause Proxy DelegateCall context)
      • No SubDAO contract being interacted with is authed on a core contract like vat, 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 SubDAO contracts
        • Upgradable contracts have the PAUSE_PROXY as their admin (i.e. the party that can upgrade)
        • Any upgradable SubDAO contracts with an admin that is not PAUSE_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 Sheet and are correct. SubDAO addresses being authed or given any permissions MUST be in the Exec Sheet. 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 SubDAO
      • SubDAO actions match Exec Sheet (only where inline with main spell code) and do not affect core contracts
      • Core contract knock-on actions (such as offboarding or setting DC to 0) are present in the exec and match the code
      • External calls for SubDAO content are NOT delegate call
      • Code does not have untoward behavior within the scope of Maker Core Contracts (e.g. up to the SubDAO proxy)
  • IF external contracts calls are present (Not SubDAOs, e.g. Starknet)
    ℹ️ Newly onboarded contracts are no longer considered external
    • Target Contract doesn't block spell execution
    • External call is NOT delegatecall
    • Target Contract doesn't have permissions on the Vat
    • Target Contract doesn't do anything untoward (e.g. interacting with unsafe contracts)
    • Contracts deployed via CREATE2 (e.g. if it looks like a vanity address) do not have selfdestruct in their code
    • MCD Pause Proxy doesn't give any approvals
    • All possible actions of the Target Contract are documented
    • Target contract is not upgradable
    • Target Contract is included in the ChainLog
    • Test Coverage is comprehensive
  • IF spell interacts with ChainLog
    • ChainLog version is incremented based on update type
      • Major -> New Vat (++.0.0)
      • Minor -> Core Module (DSS) Update (e.g. Flapper) (0.++.0)
      • Patch -> Collateral addition or addition/modification (0.0.++)
    • New addresses are added to the addresses_mainnet.sol
    • Changes are tested via testNewOrUpdatedChainlogValues
      ⚠️ This is no longer required after the refactoring PR was merged: Refactor: change testAuth* strategy #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 config
  • Ensure every spell variable is declared as public/internal
  • Ensure immutable visibility is only used when fetching addresses from the ChainLog via DssExecLib.getChangelogAddress(key) and constant is used instead for static addresses
    • Fetch addresses as type address and wrap with Like suffix interfaces inline (when making calls), UNLESS archive patterns permit otherwise (Such as MKR)
    • Use the DssExecLib Core Address Helpers where possible (e.g. DssExecLib.vat())
    • Where addresses are fetched from the 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
    • Ensure that the DssExecLib.address file is not being modified by the spell PR
    • Check all CI tests are passing as at the latest commit
      Insert most recent commit hash where CI was passing
      f685cec
    • Ensure every test function is declared as public
      • IF the test needs to run, it MUST NOT have the skipped modifier; OTHERWISE, it MUST have the skipped modifier
    • Ensure each spell action has sufficient test coverage
      List actions for which coverage was checked here
      • LITE-PSM-USDC-A Onboarding
        • Tested via testLitePSMs
      • Update PSM-USDC-A DC-IAM
        • Tested via testGeneral (using afterSpell.collaterals["PSM-USDC-A"])
      • Set up LITE-PSM-USDC-A DC-IAM
        • Tested via testGeneral (using afterSpell.collaterals["LITE-PSM-USDC-A"])
      • Add GSM Delay Exception
        • Tested via testGeneral (using afterSpell.lite_psm_mom_authority)
      • Phase 1 USDC Migration from PSM-USDC-A to LitePSM
        • Tested via test_LITE_PSM_USDC_A_MigrationPhase1
      • GSM Delay Update
        • Tested via testGeneral (using afterSpell.pause_delay)
      • Emergency Shutdown Module Minimum Threshold Update
        • Tested via testGeneral (using afterSpell.esm_min)
      • ESM Authorizations
        • Tested via testEsmAuth
      • Add LitePSM keeper network job
        • Tested via test_CRON_LITE_PSM_JOB
      • Chainlog additions
        • Tested via testChainlogIntegrity and testChainlogValues
        • Tested via test_LITE_PSM_USDC_A_JAR
      • Spark Spell
        • Tested via testSparkSpellIsExecuted
    • Ensure that any other env variable does not affect execution of the tests (for example, by inspecting the output of printenv | grep "FOUNDRY_\|DAPP_")
    • Check all tests are passing locally using make test
      • Ensure every test listed in the coverage item above is present in the logs and with the [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)

Pre-Deployment Stage

  • Wait till the Exec Doc is merged
  • Exec Doc checks
    • Exec Doc for the specified date is found in the makerdao/community GitHub repo
      ℹ️ https://github.com/makerdao/community/blob/master/governance/votes/Executive%20vote%20-%20July%2025%2C%202024.md
    • Exec Doc file name follows the format Executive vote - Month DD, YYYY.md
    • 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
      Insert your Exec Doc Hash here
      ⚠️ Script fails with date: illegal option -- d, but the hash is generated with the command below
    • 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
      0x434004820168dfce595861581ed0cf22f2e36fafb236b59a3d6019c78751be14
    • Make sure that hash above doesn't match keccak hash of the empty string (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)
    • 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
      • LITE-PSM-USDC-A Phase 1 Actions
        • 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
          • The Target Available Debt (gap) will be decreased by 20 million from 400 million to 380 million DAI
        • LITE-PSM-USDC-A DC-IAM Setup
          • Maximum Debt Ceiling (line): 50 million DAI
          • Target Available Debt (gap): 20 million DAI
          • Ceiling Increase Cooldown (ttl): 12 hours
        • LITE_PSM_MOM GSM Delay Exception Activation
          • LITE_PSM_MOM GSM Delay Exception will be activated at 0x467b32b0407Ad764f56304420Cddaa563bDab425
        • USDC Migration from PSM-USDC-A to LITE-PSM-USDC-A
          • An initial 20 million USDC will be migrated from PSM-USDC-A to LITE-PSM-USDC-A
          • At least 200 million USDC reserves should be left in reserve in PSM-USDC-A
        • GSM Pause Delay Update
          • The GSM Pause Delay will be decreased by 14 hours from 30 hours to 16 hours
        • 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
          • Authorize the Emergency Shutdown Module (ESM) on MCD_LITE_PSM_USDC_A_IN_CDT_JAR
        • LitePSM Keeper Network Job Addition
          • a keeper network job for calling permissionless LitePSM functions will be activated at 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be with the following parameters
          • Threshold at which additional DAI will be minted (fill): 15 million DAI
          • Threshold at which DAI will be burned (trim): 30 million DAI
          • Threshold at which accumulated fees are transferred to the Surplus Buffer (chug): 300,000 DAI
        • Chainlog Additions
          • Add 0xf6e72Db5454dd049d0788e411b06CfAF16853042 as MCD_LITE_PSM_USDC_A
          • Add 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341 as MCD_LITE_PSM_USDC_A_POCKET
          • Add 0x69cA348Bd928A158ADe7aa193C133f315803b06e as MCD_LITE_PSM_USDC_A_JAR
          • Add 0x5eeB3D8D60B06a44f6124a84EeE7ec0bB747BE6d as MCD_LITE_PSM_USDC_A_IN_CDT_JAR
          • Add 0x467b32b0407Ad764f56304420Cddaa563bDab425 as LITE_PSM_MOM
          • Add 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be as CRON_LITE_PSM_JOB
      • Spark Proxy Spell
        • Spark Proxy Spell will be triggered at 0x18427dB17D3113309a0406284aC738f4E649613B
    • Office hours value in the Exec Doc matches the spell
    • Sum of all payments in the Exec Doc matches the tests
      ℹ️ There are no payments in this spell
    • Exec Doc URL in the spell comment matches your Raw Exec Doc URL above
    • Exec Doc URL in the spell comment refers to the https://github.com/makerdao/community repository
    • Every action present in the spell code is present in the Exec Doc
    • Every action in the Exec Doc is present in the spell code
  • IF new commits are present in the spell
    • Copy relevant checklist items from the above and redo them
    • Ensure newly added code is covered by tests
    • Check if chainlog needs to be updated
    • Copy over and redo "Tests" section from the above
  • IF all checks pass, make sure to include explicit "Good to deploy" comment

@0xp3th1um
Copy link
Collaborator

0xp3th1um commented Jul 25, 2024

Good to deploy!

Mainnet Executive Spell Review Checklist

Development Stage

  • Preparation

    • 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
    • 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
      • LITE-PSM-USDC-A Phase 1

        • Onboard MCD_LITE_PSM_USDC_A at 0xf6e72Db5454dd049d0788e411b06CfAF16853042
        • Onboard MCD_LITE_PSM_USDC_A_POCKET at 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341

        buf: Set to 20M

      • Update PSM-USDC-A DC-IAM

        • DC-IAM line: 10B (Unchanged)
        • DC-IAM gap: Decrease for 20M from 400M to 380M
        • DC-IAM ttl: 12h (Unchanged)
      • Set up LITE-PSM-USDC-A DC-IAM

        • DC-IAM line: Set to 50M
        • DC-IAM gap: Set to 20M
        • DC-IAM ttl: Set to 12h
      • Add GSM Delay Exception

        • Activate LITE_PSM_MOM GSM Delay Exception at 0x467b32b0407Ad764f56304420Cddaa563bDab425
      • Initial USDC Migration from PSM-USDC-A to LitePSM

        • Migrate 20 million USDC from PSM-USDC-A to LITE-PSM-USDC-A
        • Leave at least 200M USDC reserves in PSM-USDC-A
      • GSM Delay Update

        • Decrease the GSM Pause Delay by 14h, from 30h to 16h
      • Emergency Shutdown Module Minimum Threshold Update

        • Increase the ESM (Emergency Shutdown Module) minimum threshold by 150k MKR from 150k MKR to 300k MKR
      • Add LitePSM keeper network job

        • sequencer.addJob( 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be )
        • fill: Set threshold at 15M DAI
        • trim: Set threshold at 30M DAI
        • chug: Set threshold at 300k DAI
      • Chainlog additions

        • Add 0xf6e72Db5454dd049d0788e411b06CfAF16853042 as MCD_LITE_PSM_USDC_A
        • Add 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341 as MCD_LITE_PSM_USDC_A_POCKET
        • Add 0x69cA348Bd928A158ADe7aa193C133f315803b06e as MCD_LITE_PSM_USDC_A_JAR
        • Add 0x5eeB3D8D60B06a44f6124a84EeE7ec0bB747BE6d as MCD_LITE_PSM_USDC_A_IN_CDT_JAR
        • Add 0x467b32b0407Ad764f56304420Cddaa563bDab425 as LITE_PSM_MOM
        • Add 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be as CRON_LITE_PSM_JOB
      • Spark Spell

        • Trigger Spark Proxy Spell at 0x18427dB17D3113309a0406284aC738f4E649613B
  • Base checks

    • Current solc version 0.8.16
    • Office hours is 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
    • Office hours value matches the Exec Sheet
    • 30 days spell expiry set in the constructor (block.timestamp + 30 days)
  • Spell description

    • Description follows the format TARGET_DATE MakerDAO Executive Spell | Hash: EXEC_DOC_HASH
    • TARGET_DATE in the description matches the target date
    • Accompanying comment above spell description follows the format // Hash: cast keccak -- "$(wget 'EXEC_DOC_URL' -q -O - 2>/dev/null)"
  • Comments inside the spell

    • Every Section text from the Exec Sheet is copied to the spell code as a comment surrounded by the set of dashes (E.g. // ----- Section text -----)
    • Every Instruction text from the Exec Sheet is copied to the spell code as // Instruction text
    • Every Instruction text have newline above it
    • IF an instruction can not be taken, it should have explanation under the instruction prefixed with // 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:
    • Every proof url from the Exec Sheet, such as Reasoning URL and Authority URL is present in the spell code under relevant section or instruction (depending on which row the url is present)
    • Every proof url from the Exec Sheet, such as 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

    • Update Foundry by running foundryup
    • Reinstall libraries by running 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'
      
    • IF submodule upgrades are present, make sure dss-exec-lib is synced as well
    • git submodule hash of dss-exec-lib (run git submodule status) matches the latest release version or newer
    • dss-interfaces library used inside lib/dss-exec-lib matches submodule used inside lib/dss-test
  • IF interfaces are present in the spell

    • Interfaces imported from dss-interfaces
      • No unused dss-interfaces
      • Only single import layout is used (e.g. import "dss-interfaces/dss/VatAbstract.sol";)
        ℹ️ Not done, but not critical!
    • Static Interfaces
      • No unused static interfaces
      • Declared static interface not present in the dss-interfaces, OTHERWISE should be imported from there
      • Interface matches deployed contract using cast interface <contract_address> command
      • Interface naming style should match with Like suffix (e.g. VatLike)
      • Each static interface declare only functions actually used in the spell code
  • IF variable declarations are present in the spell

    • IF precision units are present
      • Precision units used in the spell match their defined values:
        • WAD = 10 ** 18
        • RAY = 10 ** 27
        • RAD = 10 ** 45
      • Precision units match with Numerical Ranges
      • Each variable visibility is declared as internal
      • Each variable state mutability is declared as constant
    • IF math units are present
      • Match their defined values:
        • HUNDRED = 10 ** 2
        • THOUSAND = 10 ** 3
        • MILLION = 10 ** 6
        • BILLION = 10 ** 9
      • Match with config
      • Each variable visibility is declared as internal
      • Each variable state mutability is declared as constant
    • IF rates are present
      • Rates match generated locally via make rates pct=<pct> (e.g. pct=0.75, for 0.75%)
      • Rates match IPFS document
      • Rate variable name conforms to X_PT_Y_Z_PCT_RATE (e.g. ZERO_PT_SEVEN_FIVE_PCT_RATE for 0.75%)
      • Rate variable visibility declared as internal
      • Rate variable state mutability declared as constant
    • IF timestamps are present
      • Comment above timestamp states full date including UTC timezone
      • Timestamp converts back to the correct date
      • Timestamp converts back to the UTC timezone
      • Variable naming matches MMM_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 as internal
      • Each variable state mutability is declared as constant
  • IF new contract is present in the spell (not yet on chainlog or new to chainlog)

    • MCD_LITE_PSM_USDC_A (DssLitePsm) - 0xf6e72Db5454dd049d0788e411b06CfAF16853042
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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!
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
      • Deployer address is included into addresses_deployers.sol
    • LITE_PSM_MOM (DssLitePsmMom) - 0x467b32b0407Ad764f56304420Cddaa563bDab425
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)~~
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
      • Deployer address is included into addresses_deployers.sol
    • MCD_LITE_PSM_USDC_A_JAR (RwaJar) - 0x69cA348Bd928A158ADe7aa193C133f315803b06e
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
      • Deployer address is included into addresses_deployers.sol
    • MCD_LITE_PSM_USDC_A_IN_CDT_JAR (RwaSwapInputConduit2) - 0x5eeB3D8D60B06a44f6124a84EeE7ec0bB747BE6d
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
      • Deployer address is included into addresses_deployers.sol
    • CRON_LITE_PSM_JOB (LitePsmJob) - 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be
      • Source code is verified on etherscan
      • Compilation optimizations match deployment settings defined in the source code repo
      • GNU AGPLv3 license
      • Every maker-related constructor argument matches chainlog (e.g. vat, dai, dog, ...)
      • IF new contract have concept of wards or access control
        • Ensure PAUSE_PROXY address was relied (wards(PAUSE_PROXY) is 1)
        • Ensure that contract deployer address was denied (wards(deployer) is 0)
        • Ensure 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)
        • Ensure that there are no other Rely events except for PAUSE_PROXY and MCD_ESM (using a block explorer like etherscan)
      • Source code matches corresponding github source code (e.g. diffcheck via vscode code --diff etherscan.sol github.sol)
      • Deployer address is included into addresses_deployers.sol
  • IF core system parameter changes are present in the instructions

  • IF debt ceiling changes are present in the instructions

  • IF onboarding is present

  • IF PSM migration, onboarding or offboarding is present:

    • Insert and follow the relevant checklists below:

      PSM Migration Checklist

      • IF contracts are being on-boarded in the current spell, execute the full LitePSM On-boarding Checklist
      • IF a PSM is deprecated in the migration, execute the full PSM Off-boarding Checklist
      • IF present, max amount of gems to move (dstWant) matches the Exec Sheet
      • IF present, min amount of gems to keep (srcKeep) matches the Exec Sheet
      • Source PSM:
        • ilk matches source PSM
        • IF present, tin matches the value in the Exec Sheet
        • IF present, tout matches the value in the Exec Sheet
        • AutoLine is updated according to the Exec Sheet
      • Destination PSM:
        • ilk matches destination PSM
        • IF present, tin matches the value in the Exec Sheet
        • IF present, tout matches the value in the Exec Sheet
        • AutoLine is updated according to the Exec Sheet
        • buf matches the value in the Exec Sheet
        • fill is called conditionally (if(rush() > 0)) to ensure liquidity is immediately available after spell execution
      • Test coverage:
        • Collateral amount that is fetched from the source PSM matches the collateral is added to the destination PSM
          • vat.urns(DST_ILK, dstPsm).art is increased at least by the moved amount
          • gem balance of dstPocket is increased exactly by the moved amount
          • Dai balance of dstPsm is equal to dstBuf, UNLESS limited by the debt ceiling (line)
          • vat.urns(SRC_ILK, srcPsm).art is decreased exactly by the moved amount
          • vat.urns(SRC_ILK, srcPsm).ink is decreased exactly by the moved amount
          • gem balance of srcPsm.gemJoin() is decreased exactly by the moved amount
        • No bad debt is left behind
          • vat.vice() is unchanged after the spell execution
          • vat.sin(MCD_PAUSE_PROXY) is unchanged after the spell execution

      LitePSM On-boarding Checklist

      • Deployed Contracts
        • DssLitePsm
          • Optimizer is enabled
          • Optimize runs is set to 200
          • Contract has been reviewed by minimum 2 specialized Active Ecosystem Actors
          • Contract has been audited by an external party
          • Deployed contract matches the code in the repo
          • Constructor params:
            • ilk is named LITE-PSM-{TOKEN_SYMBOL}-A (i.e. LITE-PSM-USDC-A)
            • gem matches the expected token address
            • daiJoin matches MCD_JOIN_DAI from the chainlog
            • pocket matches the pocket address in the Exec Sheet
          • Deployer no longer has privileged access (wards(deployer) == 0)
          • MCD_PAUSE_PROXY has been authed (i.e. require(WardsLike(LITE_PSM).wards(MCD_PAUSE_PROXY) == 1))
          • Sanity check: DssLitePsm has type(uint256).max approval to spend gem on behalf of pocket
        • DssLitePsmMom
        • LitePsmJob
          • Uses the default Solidity version in dss-cron
          • Optimizer is enabled
          • Deployed contract matches the code in the repo
          • Constructor params:
            • _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")
      • Initialization
        • DssLitePsm:
          • buf is set to the value specified in the Exec Sheet
          • vow is set to MCD_VOW from the chainlog
          • MCD_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:
          • The chief (MCD_ADM) is set as the authority (i.e. MomLike(MOM).setAuthority(MCD_ADM))
        • LitePsmJob:
          • Job is added to CRON_SEQUENCER
        • MCD_VAT: new ilk is initialized
        • MCD_JUG: new ilk is initialized
        • MCD_SPOT:
          • Sanity check: Dai parity (par) current value is 1 (1 * RAY)
          • Collateralization ratio (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 corrected
          • IF a new pip is being used:
            • pip is set for the ilk
            • pip is a DSValue instance
            • The value on pip is set to 1 (1 * WAD)
            • pip deployer is no longer the owner
            • MCD_PAUSE_PROXY is the owner on pip
          • OTHERWISE when reusing an existing pip:
            • pip is set for the ilk
            • pip in the chainlog matches gem symbol (i.e. PIP_USDC for USDC)
        • ILK_REGISTRY: new ilk is added to the registry
        • CHAINLOG:
          • DssLitePsm is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
          • pocket is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
          • DssLitePsmMom is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
          • LitePsmJob is added to the chainlog and addresses_mainnet.sol according to the Exec Sheet
          • IF a new pip is being added, it is added to the chainlog and addresses_mainnet.sol as PIP_{TOKEN_SYMBOL} (i.e. PIP_USDC)
      • Test coverage:
        • DssLitePsm:
          • vow is set to MCD_VOW
          • buf matches the Exec Sheet
          • MCD_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)
          • E2E tests:
            • buyGem works as expected
            • sellGem works as expected
            • buyGemNoFee works as expected
            • sellGemNoFee works as expected
        • DssLitePsmMom:
          • Chief (MCD_ADM) is set as the authority (i.e. MomLike(MOM).authority() == MCD_ADM)
          • E2E tests:
            • halt works as expected
        • LitePsmJob:
          • Job is added to 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")
          • E2E tests:
            • workable returns the correct value:
              • IF rush() > 0, returns (true, litePsm.fill.selector)
              • OTHERWISE IF cut() > 0, returns (true, litePsm.chug.selector)
              • OTHERWISE IF gush() > 0, returns (true, litePsm.trim.selector)
              • OTHERWISE returns (false, "")
            • work has the desired effect:
              • IF rush() > 0, fill is called
              • OTHERWISE IF cut() > 0, chug is called
              • OTHERWISE IF gush() > 0, trim is called
              • OTHERWISE reverts
        • 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)
        • 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:
          • New ilk is added to the registry
          • name matches gem name
          • symbol matches gem symbol
          • class for join-less ilks is used (REG_CLASS = 6)
          • gem matches the configured gem
          • pip matches the configured pip
          • gemJoin is set to address(0)
          • clip is set to address(0)

      ## PSM Off-boarding Checklist

      • ilk is removed from AutoLine
      • ilk line is set to 0
      • ink for the PSM is set to 0 on MCD_VAT after execution, UNLESS there has been a donation
      • Global Line is adjusted accordingly
      • ilk is removed from ILK_REGISTRY
      • PSM contracts (Psm, GemJoin and others, as applicable) are being removed from the chainlog
      • Chainlog version is bumped: {x}.{y+1}.0
      • PSM contracts (Psm, GemJoin and others, as applicable) are being scuttled
        • MCD_PAUSE_PROXY is de-authed from all applicable contracts
  • IF collateral offboarding is present in the spell

    • 1st stage collateral offboarding
      • Collateral type (ilk) is removed from AutoLine (MCD_IAM_AUTO_LINE) IF currently enabled
      • Collateral debt ceiling (vat.ilk.line) is set to 0
      • Global debt ceiling (vat.Line) decreased by the total amount of offboarded ilks
    • 2nd stage collateral offboarding
      • All 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 to 0 IF requested by governance
      • Flat keeper incentive (tip) is set to 0 IF requested by governance
      • Relative keeper incentive (chip) is set to 0 IF requested by governance
      • Max liquidation amount (hole) is adjusted via DssExecLib.setIlkMaxLiquidationAmount(ilk, amount) IF requested by governance
      • Relevant clipper contract (MCD_CLIP_) is active (i.e. stopped is 0)
      • Liquidations are triggered via (depending on governance instruction):
        • EITHER liquidation ratio (spotter.ilk.mat) being set very high in the spell (using DssExecLib.setValue(DssExecLib.spotter(), ilk, "mat", ratio))
        • OR via enabling linear interpolation (DssExecLib.linearInterpolation(name, target, ilk, what, startTime, start, end, duration))
          • Ensure name format matches "XXX-X Offboarding"
          • Ensure target matches DssExecLib.spotter() address
          • Ensure ilk format matches collateral type (ilk) name ("XXX-X")
          • Ensure what matches string "mat"
          • Ensure startTime matches block.timestamp
          • Ensure start uses variable CURRENT_XXX_A_MAT
          • Ensure start matches current spotter.ilk.mat value
          • Ensure end uses variable TARGET_XXX_A_MAT
          • Ensure end value matches the instruction
          • Ensure end allows liquidation of all remaining vaults (end is bigger than collateral_type_collateralization_ratio * risk_multiplier_factor)
          • Ensure duration matches the instruction
      • Spotter price is updated via DssExecLib.updateCollateralPrice(ilk) IF collateral have no running oracle (i.e. relevant PIP_ contract have outdated zzz value)
      • Spotter price is updated after all other actions
      • Offboarding is tested at least via _checkIlkClipper helper
  • IF RWA updates are present

    • IF doc is updated
      • _updateDoc helper is copied one-to-one from the archive and defined above actions
      • _updateDoc(ilk, doc) is called in the spell
    • IF debt ceiling is updated
      • IF AutoLine update is requested by the Exec Sheet
      • IF regular debt ceiling (vat.ilk.line) update is requested by the Exec Sheet
      • Liquidation oracle price is bumped via RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).bump(ilk, val) pattern
        • Comment above bump explains val computation via // Note: the formula is: "debt_ceiling * [ (1 + rwa_stability_fee ) ^ (minimum_deal_duration_in_years) ] * liquidation_ratio"
        • Comment above bump provides locally executable formula (e.g. // bc -l <<< 'scale=18; 50000000 * e(l(1.07) * (3342/365)) * 1.00' | cast --to-wei)
          • The formula matches the example provided above
          • debt_ceiling in the executable formula matches new debt ceiling set in the spell or the maximum possible debt ceiling in case of the enabled AutoLine
          • rwa_stability_fee in the executable formula matches stability fee of the specified RWA found on chain
          • minimum_deal_duration_in_years in the executable formula matches number found in the Exec Sheet of the spell containing relevant RWA onboarding
          • liquidation_ratio in the executable formula matches liquidation ratio of the specified RWA found on chain
          • Executing formula locally provides integer number that matches the val in the spell
        • val makes sense in context of the rate mechanism
      • IF multiple RWA ilks are being combined into one, val calculation is done once per ilk and added to make the total, with separate executable formulas provided in comments. The existing val value can be retrieved by calling read() on PIP_RWAXX and converting the result into decimal
      • Oracle price is updated via DssExecLib.updateCollateralPrice(ilk)
      • IF soft liquidation explicitly requested to be triggered (via .tell(ilk)) AND debt ceiling is 0 (OR is being set to 0 in the current spell)
        • RwaLiquidationOracle.tell(ilk) call is present
        • IF RWAXX_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

    • IF MKR transfers are present
      • Recipient address in the instruction is in the checksummed format
      • Recipient address matches Exec Sheet
      • Recipient address variable name matches one found in addresses_wallets.sol
      • Transfer amount matches Exec Sheet
      • Transfer amount is specified with (at least) 2 decimals using ether keyword
      • IF ether 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 via testMKRPayments test
      • ~~Sum of all MKR transfers tested in testMKRPayments matches number in the Exec Sheet
    • IF DAI surplus buffer transfers are present~~
      • Recipient address in the instruction is in the checksummed format
      • Recipient address matches Exec Sheet
      • Recipient address variable name matches one found in addresses_wallets.sol
      • Transfer amount matches Exec Sheet
      • The transfers are tested via testDAIPayments test
      • ~~Sum of all DAI transfers tested in testDAIPayments matches number in the Exec Sheet
    • IF MKR 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 Sheet
      • usr (Vest recipient address) matches Exec Sheet
      • usr address in the instruction is in the checksummed format
      • usr address variable name match one found in addresses_wallets.sol
      • tot (Total stream amount) matches Exec Sheet
      • IF ether 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 Sheet, account for leap days
      • bgn (Vest start timestamp) matches Exec Sheet
      • tau is expressed as bgn - fin (i.e. MONTH_DD_YYYY - MONTH_DD_YYYY)
      • fin (Vest end timestamp) matches Exec Sheet
      • eta (Vest cliff duration) matches the following logic
        • IF eta is explicitly specified in the Exec Sheet, then the values match
        • IF eta and clf (Cliff end timestamp) are not specified in the Exec Sheet, then eta is 0
        • IF clf is specified, but clf <= bgn, then eta is 0
        • IF clf is specified and clf > bgn, eta is expressed as clf - bgn (i.e. MONTH_DD_YYYY - MONTH_DD_YYYY)
      • IF mgr (Vest manager address) is specified in the Exec Sheet, matches the value, OTHERWISE matches address(0)
      • Ensure that max vesting rate (cap) is enough for the new streams
        • The maximum vesting rate (tot divided by tau) <= the maximum vest streaming rate (cap)
        • The maximum vesting rate (tot divided by tau) > the maximum vest streaming rate (cap)
        • Calculate new 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)
      • ~~IF max vesting rate (cap) is changed in the spell
        • Governance facilitators were notified
        • Exec Sheet contain explicit instruction
        • Exec Sheet contain explicit instruction
      • ~~IF MKR stream (DssVestTransferrable) is present
        • Vest contract's MKR allowance increased by the cumulative total (the sum of all tot values)
        • Ensure allowance increase follows archive patterns
      • Tested via testVestDAI or testVestMKR
    • IF MKR or DAI vest termination (Yank) is present
      • Yanked stream ID matches Exec Sheet
      • MCD_VEST_MKR_TREASURY chainlog address is used for MKR stream yank
      • MCD_VEST_DAI chainlog address is used for DAI stream yank
      • Tested via testYankDAI or testYankMKR
  • IF SubDAO-related content is present

    • IF SubDAO provides SubProxy spell address
      • SubDAO spell address matches Exec Sheet
      • Executed via ProxyLike(SUBDAO_PROXY).exec(SUBDAO_SPELL, abi.encodeWithSignature("execute()"));
      • Execution is NOT delegate call
      • IF SubDAO spell deployer is a smart contract (e.g. multisig or factory), ensure the deployer address is in addresses_deployers.sol as an entry
      • Ensure 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 scripts
        ℹ️ This is done later on the Tenderly simulation!
    • IF SubDAO provides instructions to be executed by the main spell (i.e. that will operate within Pause Proxy DelegateCall context)
      • No SubDAO contract being interacted with is authed on a core contract like vat, 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 SubDAO contracts
        • Upgradable contracts have the PAUSE_PROXY as their admin (i.e. the party that can upgrade)
        • Any upgradable SubDAO contracts with an admin that is not PAUSE_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 Sheet and are correct. SubDAO addresses being authed or given any permissions MUST be in the Exec Sheet. 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 SubDAO
      • SubDAO actions match Exec Sheet (only where inline with main spell code) and do not affect core contracts
      • Core contract knock-on actions (such as offboarding or setting DC to 0) are present in the exec and match the code
      • External calls for SubDAO content are NOT delegate call
      • Code does not have untoward behavior within the scope of Maker Core Contracts (e.g. up to the SubDAO proxy)
  • IF external contracts calls are present (Not SubDAOs, e.g. Starknet)

    • Target Contract doesn't block spell execution
    • External call is NOT delegatecall
    • Target Contract doesn't have permissions on the Vat
    • Target Contract doesn't do anything untoward (e.g. interacting with unsafe contracts)
    • Contracts deployed via CREATE2 (e.g. if it looks like a vanity address) do not have selfdestruct in their code
    • MCD Pause Proxy doesn't give any approvals
    • All possible actions of the Target Contract are documented
    • Target contract is not upgradable
    • Target Contract is included in the ChainLog
    • Test Coverage is comprehensive
  • IF spell interacts with ChainLog

    • ChainLog version is incremented based on update type
      • Major -> New Vat (++.0.0)
      • Minor -> Core Module (DSS) Update (e.g. Flapper) (0.++.0)
      • Patch -> Collateral addition or addition/modification (0.0.++)
    • New addresses are added to the addresses_mainnet.sol
    • Changes are tested via testNewOrUpdatedChainlogValues
      ℹ️ This is not true, the test code has been refactored and tested by different functions, test coverage below!
  • Ensure every spell variable is declared as public/internal

  • Ensure immutable visibility is only used when fetching addresses from the ChainLog via DssExecLib.getChangelogAddress(key) and constant is used instead for static addresses

    • Fetch addresses as type address and wrap with Like suffix interfaces inline (when making calls), UNLESS archive patterns permit otherwise (Such as MKR)
    • Use the DssExecLib Core Address Helpers where possible (e.g. DssExecLib.vat())
    • Where addresses are fetched from the 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

    • Ensure that the DssExecLib.address file is not being modified by the spell PR
    • Check all CI tests are passing as at the latest commit
      Insert most recent commit hash where CI was passing
      f685cec
    • Ensure every test function is declared as public
      • IF the test needs to run, it MUST NOT have the skipped modifier; OTHERWISE, it MUST have the skipped modifier
    • Ensure each spell action has sufficient test coverage
      List actions for which coverage was checked here
      [x] LITE-PSM-USDC-A Onboarding
      testLitePSMs()
      [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()
    • Ensure that any other env variable does not affect execution of the tests (for example, by inspecting the output of printenv | grep "FOUNDRY_\|DAPP_")
    • Check all tests are passing locally using make test
      • Ensure every test listed in the coverage item above is present in the logs and with the [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)

Pre-Deployment Stage

  • Wait till the Exec Doc is merged
  • Exec Doc checks
    • Exec Doc for the specified date is found in the makerdao/community GitHub repo

    • Exec Doc file name follows the format Executive vote - Month DD, YYYY.md

    • 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

    • 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

    • Make sure that hash above doesn't match keccak hash of the empty string (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 )

    • 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

      • LITE-PSM-USDC-A Phase 1 Actions

        • 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

        • The Target Available Debt (gap) will be decreased by 20 million from 400 million to 380 million DAI.
      • LITE-PSM-USDC-A DC-IAM Setup

        • Maximum Debt Ceiling (line): 50 million DAI
        • Target Available Debt (gap): 20 million DAI
        • Ceiling Increase Cooldown (ttl): 12 hours
      • LITE_PSM_MOM GSM Delay Exception Activation

        • LITE_PSM_MOM GSM Delay Exception will be activated at 0x467b32b0407Ad764f56304420Cddaa563bDab425.
      • USDC Migration from PSM-USDC-A to LITE-PSM-USDC-A

        • An initial 20 million USDC will be migrated from PSM-USDC-A to LITE-PSM-USDC-A.
      • GSM Pause Delay Update

        • The GSM Pause Delay will be decreased by 14 hours from 30 hours to 16 hours.
      • 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

        • Authorize the Emergency Shutdown Module (ESM) on MCD_LITE_PSM_USDC_A_IN_CDT_JAR
      • LitePSM Keeper Network Job Addition

        • a keeper network job for calling permissionless LitePSM functions will be activated at 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be with the following parameters:

          • Threshold at which additional DAI will be minted (fill): 15 million DAI.
          • Threshold at which DAI will be burned (trim): 30 million DAI.
          • Threshold at which accumulated fees are transferred to the Surplus Buffer (chug): 300,000 DAI.
      • Chainlog Additions

        • Add 0xf6e72Db5454dd049d0788e411b06CfAF16853042 as MCD_LITE_PSM_USDC_A.
        • Add 0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341 as MCD_LITE_PSM_USDC_A_POCKET.
        • Add 0x69cA348Bd928A158ADe7aa193C133f315803b06e as MCD_LITE_PSM_USDC_A_JAR.
        • Add 0x5eeB3D8D60B06a44f6124a84EeE7ec0bB747BE6d as MCD_LITE_PSM_USDC_A_IN_CDT_JAR.
        • Add 0x467b32b0407Ad764f56304420Cddaa563bDab425 as LITE_PSM_MOM.
        • Add 0x689cE517a4DfCf0C5eC466F2757D324fc292C8Be as CRON_LITE_PSM_JOB.
      • Spark Proxy Spell
        -Spark Proxy Spell will be triggered at 0x18427dB17D3113309a0406284aC738f4E649613B. This proxy spell will take the following action:

    • Office hours value in the Exec Doc matches the spell

    • Sum of all payments in the Exec Doc matches the tests

    • Exec Doc URL in the spell comment matches your Raw Exec Doc URL above

    • Exec Doc URL in the spell comment refers to the https://github.com/makerdao/community repository

    • Every action present in the spell code is present in the Exec Doc

    • Every action in the Exec Doc is present in the spell code

  • IF new commits are present in the spell
    • Copy relevant checklist items from the above and redo them
    • Ensure newly added code is covered by tests
    • Check if chainlog needs to be updated
    • Copy over and redo "Tests" section from the above
  • IF all checks pass, make sure to include explicit "Good to deploy" comment

@amusingaxl
Copy link
Contributor Author

Deployment Stage

  • Wait for at least two "good to deploy" comments (containing local tests) from the official reviewers
  • Pre-deploy setup and checks (currently via dapptools)
    • Set local environment variables (.sethrc)
      • Deployer
        • Avoid using the same deployer for mainnet and testnet (to avoid deploying contracts with the same address but different sources)
        • export ETH_PASSWORD=~/.env/password.txt
        • export ETH_KEYSTORE=~/.ethereum/keystore
        • export ETH_FROM=<address>
      • EIP1559
        • Run make estimate to estimate gas
        • export ETH_GAS=X with the output of the command above + a safety margin (e.g. export ETH_GAS=6_000_000)
        • Check current gas price using seth gas-price and set ETH_GAS_PRICE accordingly (e.g. 50 gwei)
        • Consider adding margin to account for spikes (e.g. current gas price 25 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)
        • Check current gas priority fee and set ETH_PRIO_FEE accordingly
        • export 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 URL
      • export ETHERSCAN_API_KEY=<key> to set Etherscan API KEY
      • source .sethrc to make env vars available
    • Check local env
      • seth ls
      • seth chain
  • Deploy spell on mainnet
    • make deploy
    • Ensure src/test/config.sol is edited correctly
      • deployed_spell: address(<deployed_spell_address>)
      • deployed_spell_created: <timestamp>
      • deployed_spell_block: <block number>
      • validate the above values via make deploy-info tx=<tx_hash>
    • Ensure spell is verified on etherscan
    • Ensure local tests PASS against deployed spell run via the deploy script
    • Push auto-generated add deployed spell info commit
  • Cast spell on a newly created Tenderly Testnet
    • Create testnet and cast deployed spell there using make cast-on-tenderly spell=0x... command
    • Check that returned public explorer url is publicly accessible (e.g. using incognito browser mode)
      https://dashboard.tenderly.co/explorer/vnet/b2e40858-22de-4b53-8f64-9d31ac604f2a
    • IF cast-on-tenderly command is executed several times for the same spell, delete all testnets of the same name except the last one
  • Archive Spell via make archive-spell for the current date (or make archive-spell date="YYYY-MM-DD") using Target Date inside the Exec Doc
  • Commit & push changes for review
  • Wait for CI to PASS
  • Post a comment inside the PR containing links to the deployed spell and Tenderly Testnet
  • Notify the reviewers (e.g. "the spell was deployed")

@SidestreamColdMelon
Copy link
Contributor

TLDR: Good to handover

Deployed Stage

  • Source code settings
    • Deployed spell is verified on etherscan
    • Optimization enabled: false UNLESS the contract size is too big AND all mitigation strategies (i.e.: removing revert strings) have failed
    • Default evmVersion
    • GNU AGPLv3 license
  • Source code validity
    • Deployed spell code matches source on github. (can be checked via make diff-deployed-spell or manually)
      ℹ️ Verified code exactly matches forge flatten src/DssSpell.sol -o out/flat.sol output
    • No new changes are made after previously given "good to deploy"
  • Deployed spell Etherscan checks
    • Automated checks via make 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)
      • Verified
      • Valid license
      • Version matches
      • Optimizations are disabled
      • dss-exec-lib library address used (under 'Libraries Used') matches the hardcoded local DssExecLib.address file
      • deployed_spell_created matches deployment timestamp
        ⚠️ 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 script
      • deployed_spell_block matches deployment block number
        ⚠️ As above
    • Manual checks
      • Ensure make deploy-info tx=<tx> matches config
        • deployed_spell_created timestamp
        • deployed_spell_block block number
      • Check again that the PR did not modify the DssExecLib.address file (e.g. look under the 'Files Changed' PR tab, etc.)
      • Ensure Etherscan Libraries Used matches DssExecLib Latest Release
      • (For your tests to be accurate) git submodule hash matches dss-exec-lib latest release's tag commit and inspect diffs if doesn't match to ensure expected behaviour (Currently Non-Critical pending the next DssExecLib release, double check that the ExecLib used by the contract matches the latest release)
        ⚠️ The hash doesn't match as in multiple previous spells. Latest release v0.0.9 has hash of c0d3c6c 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: makerdao/dss-exec-lib@v0.0.9...69b658f#diff-72201ff20380f5c7fc89281be3ad2dd6bd5a992f246d41d6d9d97f71e078d40d. The only major difference between deployed and the imported library is the new setRWAIlkDebtCeiling, which we're not using in this particular spell
  • Tenderly Testnet checks
  • Archive checks
    • make diff-archive-spell for current date or make diff-archive-spell date="YYYY-MM-DD"
    • Ensure date corresponds to target Exec Doc date
  • Tests
    • Ensure that the DssExecLib.address file is not being modified by the spell PR
    • Check all CI tests are passing as at the latest commit
      Insert most recent commit hash where CI was passing
      f750e59
    • Ensure that any other env variable does not affect execution of the tests (for example, by inspecting the output of printenv | grep "FOUNDRY_\|DAPP_")
    • Check all tests are passing locally using 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)
  • Additional checks
    • testBytecodeMatches pass
    • No delegatecall code inside verified code
    • No selfdestruct code present in the deployed code

@0xp3th1um
Copy link
Collaborator

Good to handover

Deployed Stage

  • Source code settings
    • Deployed spell is verified on etherscan
    • Optimization enabled: false UNLESS the contract size is too big AND all mitigation strategies (i.e.: removing revert strings) have failed
    • Default evmVersion
    • GNU AGPLv3 license
  • Source code validity
    • Deployed spell code matches source on github. (can be checked via make diff-deployed-spell or manually)
    • No new changes are made after previously given "good to deploy"
  • Deployed spell Etherscan checks
    • Automated checks via make check-deployed-spell
      • Verified
      • Valid license
      • Version matches
      • Optimizations are disabled
      • dss-exec-lib library address used (under 'Libraries Used') matches the hardcoded local DssExecLib.address file
      • deployed_spell_created matches deployment timestamp
        ⚠️ The script gives a wrong result locally, checked manually below
      • deployed_spell_block matches deployment block number
        ⚠️ The script gives a wrong result locally, checked manually below
    • Manual checks
      • Ensure make deploy-info tx=<tx> matches config
        ℹ️ tx=0xc9923d961f228ab78deb565287664615b13f0f53431873bd8ac582710b1b3f45
        • deployed_spell_created timestamp
          ℹ️ timestamp: 1721926643
        • deployed_spell_block block number
          ℹ️ block: 20384902
      • Check again that the PR did not modify the DssExecLib.address file (e.g. look under the 'Files Changed' PR tab, etc.)
      • Ensure Etherscan Libraries Used matches DssExecLib Latest Release
      • (For your tests to be accurate) git submodule hash matches dss-exec-lib latest release's tag commit and inspect diffs if doesn't match to ensure expected behaviour (Currently Non-Critical pending the next DssExecLib release, double check that the ExecLib used by the contract matches the latest release)
        ⚠️ Step above skipped, there is a current mismatch as in previous spells, not critical
  • Tenderly Testnet checks
  • Archive checks
    • make diff-archive-spell for current date or make diff-archive-spell date="YYYY-MM-DD"
    • Ensure date corresponds to target Exec Doc date
  • Tests
    • Ensure that the DssExecLib.address file is not being modified by the spell PR
    • Check all CI tests are passing as at the latest commit
      Insert most recent commit hash where CI was passing
      f750e59
    • Ensure that any other env variable does not affect execution of the tests (for example, by inspecting the output of printenv | grep "FOUNDRY_\|DAPP_")
    • Check all tests are passing locally using 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)

Copy link
Contributor

@SidestreamColdMelon SidestreamColdMelon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handover and Merge Stage

  • Check that the spell address posted by the crafter in new-spells is correct
  • Confirm the address in the new-spells channel (via a separate "reply to" message, restating the address to avoid edits)
    • Wait until responsible governance facilitator confirms handover in new-spells
  • Ensure that no changes were made to the code since the spell was deployed and archived
  • Approve spell PR for merge via 'Approve' review option

@0xp3th1um
Copy link
Collaborator

Handover and Merge Stage

  • Check that the spell address posted by the crafter in new-spells is correct
  • Confirm the address in the new-spells channel (via a separate "reply to" message, restating the address to avoid edits)
    • Wait until responsible governance facilitator confirms handover in new-spells
  • Ensure that no changes were made to the code since the spell was deployed and archived
  • Approve spell PR for merge via 'Approve' review option

@amusingaxl amusingaxl merged commit 132295d into master Jul 25, 2024
3 checks passed
@amusingaxl amusingaxl deleted the 2024-07-25 branch July 25, 2024 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants