Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

2024-02-07 Goerli Spell #245

Merged
merged 16 commits into from
Feb 7, 2024
Merged

2024-02-07 Goerli Spell #245

merged 16 commits into from
Feb 7, 2024

Conversation

oddaf
Copy link
Member

@oddaf oddaf commented Jan 31, 2024

Description

This PR implements 2024-02-07 goerli spell based on the relevant Exec Sheet.

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 Goerli changelog or known
  • Notify any external teams affected by the spell so they have the opportunity to review
  • Deploy spell to Goerli ETH_GAS_LIMIT="XXX" ETH_GAS_PRICE="YYY" make deploy
  • Ensure contract is verified on Goerli etherscan
  • Change test to use Goerli spell address and deploy timestamp
  • Cast spell on Goerli make spell="0x-deployed-spell-address" cast-spell
  • Run make archive-spell or make date="YYYY-MM-DD" archive-spell to make an archive directory and copy DssSpell.sol, DssSpell.t.sol and DssSpell.t.base.sol
  • squash and merge this PR

@oddaf oddaf requested a review from amusingaxl January 31, 2024 17:50
@oddaf oddaf self-assigned this Jan 31, 2024
@DaiFoundation-DevOps
Copy link

DaiFoundation-DevOps commented Jan 31, 2024

CLA assistant check
All committers have signed the CLA.

src/DssSpell.sol Outdated Show resolved Hide resolved
lib/dss-test Outdated Show resolved Hide resolved
Comment on lines 459 to 460
string RWA009_OLDDOC = "QmfEgZuiw6wsTRUYerdPZNUrqDXSGM6Nm4fM3nG7nNbEjT";
string RWA009_NEWDOC = "QmPzuLuJ5Xq6k6Hbop1W5s4V9ksvafYoqcW9sU5QRwz5h1";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: keep alignment consistent within the block only.

Suggested change
string RWA009_OLDDOC = "QmfEgZuiw6wsTRUYerdPZNUrqDXSGM6Nm4fM3nG7nNbEjT";
string RWA009_NEWDOC = "QmPzuLuJ5Xq6k6Hbop1W5s4V9ksvafYoqcW9sU5QRwz5h1";
string RWA009_OLDDOC = "QmfEgZuiw6wsTRUYerdPZNUrqDXSGM6Nm4fM3nG7nNbEjT";
string RWA009_NEWDOC = "QmPzuLuJ5Xq6k6Hbop1W5s4V9ksvafYoqcW9sU5QRwz5h1";

Copy link
Member Author

Choose a reason for hiding this comment

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

updated

@@ -1730,4 +1730,4 @@ contract Config {
offboarding: false
});
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Careful with the trailing new-line removal.

Please make sure your editor has editorconfig support to avoid that.

Copy link
Member Author

Choose a reason for hiding this comment

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

updated.

@oddaf oddaf marked this pull request as ready for review February 3, 2024 16:14
@0xp3th1um
Copy link
Collaborator

0xp3th1um commented Feb 5, 2024

the Delegate Compensation details are missing, even if payments are skipped on Goerli they are added to the spell as comments in previous spells
UPDATE: they are in previous spells but they are not mandatory.

src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
src/DssSpell.sol Outdated Show resolved Hide resolved
@SidestreamColdMelon
Copy link
Contributor

Goerli 2024-02-07

Spell Actions (Per Exec Sheet):

  • Read spell actions and instructions from the Exec Sheet
  • List the actions being performed in this spell
  • Auction Parameter Updates
    • Increase the WSTETH-A Local Liquidation Limit (ilk.hole) by 15 million DAI from 15 million DAI to 30 million DAI.
    • Increase the WSTETH-B Local Liquidation Limit (ilk.hole) by 10 million DAI from 10 million DAI to 20 million DAI.
    • Decrease the WBTC-A Local Liquidation Limit (ilk.hole) by 20 million DAI from 30 million DAI to 10 million DAI.
    • Decrease the WBTC-B Local Liquidation Limit (ilk.hole) by 5 million DAI from 10 million DAI to 5 million DAI.
    • Decrease the WBTC-C Local Liquidation Limit (ilk.hole) by 10 million DAI from 20 million DAI to 10 million DAI.
    • Increase the Global Liquidation Limit (Hole) by 50 million DAI from 100 million DAI to 150 million DAI.
  • Push GUSD out of input conduit
    • Raise PSM-GUSD-A DC to 597,660 DAI
    • Call push() on MCD_PSM_GUSD_A_INPUT_CONDUIT_JAR (use push(uint256 amt)) to push 597,659 GUSD
    • Call void() on MCD_PSM_GUSD_A_JAR
    • Set PSM-GUSD-A DC to 0 DAI
  • Aave SparkLend Revenue Share
    • Transfer 100,603 DAI to 0x464C71f6c2F760DdA6093dCB91C24c39e5d6e18c
  • RWA009 doc Update
    • Update HVBank (RWA009-A) doc to QmPzuLuJ5Xq6k6Hbop1W5s4V9ksvafYoqcW9sU5QRwz5h1
  • Delegate Compensation
    • 0xDefensor - 41.67 MKR - 0x9542b441d65B6BF4dDdd3d4D2a66D8dCB9EE07a9
    • BLUE - 41.67 MKR - 0xb6C09680D822F162449cdFB8248a7D3FC26Ec9Bf
    • BONAPUBLICA - 41.67 MKR - 0x167c1a762B08D7e78dbF8f24e5C3f1Ab415021D3
    • Cloaky - 41.67 MKR - 0x869b6d5d8FA7f4FFdaCA4D23FFE0735c5eD1F818
    • TRUE NAME - 41.67 MKR - 0x612F7924c367575a0Edf21333D96b15F1B345A5d
    • PBG - 13.89 MKR - 0x8D4df847dB7FfE0B46AF084fE031F7691C6478c2
    • UPMaker - 13.89 MKR - 0xbB819DF169670DC71A16F58F55956FE642cc6BcD
    • vigilant - 13.89 MKR - 0x2474937cB55500601BCCE9f4cb0A0A72Dc226F61
    • WBC - 13.89 MKR - 0xeBcE83e491947aDB1396Ee7E55d3c81414fB0D47
    • JAG - 13.71 MKR - 0x58D1ec57E4294E4fe650D1CB12b96AE34349556f

Development Stage

  • Office Hours
    • OFF (On Goerli the deployed spell is cast with a pause delay of 60 sec.)
  • 30 days spell expiry in constructor (block.timestamp + 30 days)
  • No Exec Doc Hash on Goerli
  • Spell Description
    • Ensure description exactly matches 'Goerli Spell'
  • Ensure the comments inside the spell action are correct:
    • Every Section text from the Exec Sheet should be copied as comment to the spell code (above the code segment that implements the action)
      Spark - AAVE Revenue Share doesn't match Aave SparkLend Revenue Share in the sheet
      • is surrounded by the set of dashes (E.g. // ----- Section text -----)
    • Every Instruction text Exec Sheet should be:
      • copied to the spell code as // Instruction text
        ⚠️ Some instructions were not copied, due to their irrelevance to goerli
      • have newline above it
    • Every Reasoning URL and Authority URL from the Exec Sheet should be present under relevant section or instruction in the spell code (depending on which row the link is present)
      ❌ voting url is missing from the Auction Parameter Updates section
      • Every Reasoning URL and Authority URL should 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/
    • If action in the spell doesn't have relevant instruction (e.g.: chainlog version bump), it should have explanation prefixed with // Note:
    • If an instruction can not be taken, it should have a comment under the instruction prefixed with // Note: (e.g.: // Note: Payments are skipped on goerli)
  • Local Environment Actions
    • Update Foundry by running foundryup
    • Reinstall libraries by running rm -r 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'
      
    • Library Checks
      • dss-exec-lib
        • If submodule upgrades are present make sure dss-exec-lib is synced as well
        • (Non-critical) Submodule hash matches the latest release version (NOTE: dss-exec-lib as installed locally will use GitHub code more recent than the 0.0.9 release until the 0.0.10 release)
      • dss-test
  • Rate constants used are correct
    • Manual check 1: Calculate rates using make rates pct=<pct> (e.g. pct=0.75, for 0.75%)
    • Manual check 2: Compare rates used against IPFS rate list
    • Variable name conforms to X_PT_Y_Z_PCT_RATE (e.g. ZERO_PT_SEVEN_FIVE_PCT_RATE for 0.75%, SIX_PCT_RATE for 6.00%)
    • Visibility is internal
    • State mutability is constant
  • Constants Match
    • Precision unit constants used match their defined values
      • WAD = 10 ** 18
      • RAY = 10 ** 27
      • RAD = 10 ** 45
      • Visibility is internal
      • State mutability is constant
      • (Non-critical) Ensure they match with ds-math and the Numerical Ranges
    • Math unit constants used match their defined values
      • HUNDRED = 10 ** 2
      • THOUSAND = 10 ** 3
      • MILLION = 10 ** 6
      • BILLION = 10 ** 9
      • Visibility is internal
      • State mutability is constant
      • (Non-critical) Ensure they match with config
  • Address Declaration
    • Address Constants
      • Address is not in the ChainLog
      • Variable name matches corresponding entry in an addresses.sol file
      • Address value matches corresponding entry in an addresses.sol file
      • Visibility is internal
      • State mutability is constant
    • Address Immutables
      • Use the DssExecLib Core Address Helpers instead of getChangelogAddress() whenever possible (e.g. DssExecLib.vat())
      • Follow pattern address internal immutable KEY_NAME = DssExecLib.getChangelogAddress(KEY_NAME)
      • Variable name matches ChainLog key name
        • Exceptions must follow archive patterns (e.g. MKR for MCD_GOV)
      • Instantiate as address type
        • Exceptions must follow archive patterns (e.g. GemLike for MKR)
      • Visibility is internal
      • State mutability is immutable
  • String Constants
    • IPFS hashes or DAO resolutions
      • IPFS hashes and DAO resolutions match the exec doc
      • The variable is named dao_resolutions
      • if multiple dao resolutions are present
        • they are located in the same string constant and are comma separated
        • The comment above the the variable states: Comma-separated list of DAO resolutions IPFS hashes
    • Must be TOP LEVEL (or ds pause will reject)
    • Name of the variable matches purpose per EXEC DOC
    • Visibility is public
    • State mutability MUST BE constant
  • Deployed Contracts (not yet on chainlog or new to chainlog)
    • Verified on etherscan
    • Optimizations match Repo
    • GNU AGPLv3 license
    • Constructor args ok (e.g. vat, dai, dog, ...)
    • Wards ok (pause proxy relied, deployer denied)
      • MCD_ESM is already relied / being relied in this spell (as approved by Governance Facilitators) in order to allow de-authing the pause proxy during Emergency Shutdown, via denyProxy.
    • Matches corresponding github source code (i.e. diffcheck via vscode code --diff etherscan.sol github.sol)
    • Ensure deployer address is included into addresses_deployers.sol (to keep up to date)
  • Core System Parameter Changes
  • Debt Ceiling Changes
  • Onboarding (insert relevant checklists inline here)
  • Offboarding (Lerp mat)
    • 1st Stage Spell Actions
      • Remove Ilk from Autoline
      • Set Ilks Debt Ceilings to 0
      • Cache Ilks line to Reduce in the Global Debt Ceiling
      • Decrease Global Debt Ceiling by Total Amount of Offboarded Ilks line Cached
    • 2nd Stage Spell Actions
      • Set Ilk Liquidation Penalty chop to 0
      • Set Keeper Incentive Flat Rate tip to 0
      • Check IF chip is required to be adjusted as well
      • Use DssExecLib.linearInterpolation
        • name Format matches "XXX-A Offboarding"
        • target matches spotter
        • ilk Format matches "XXX-A"
        • what matches mat
        • startTime matches block.timestamp
        • start matches Var CURRENT_XXX_A_MAT
        • end matches Var TARGET_XXX_A_MAT (Match Exec Sheet & Risk Computations)
          • Check IF Target mat Covers All Remaining Vaults CR times Risk Multiplier Factor
        • duration matches Exec Sheet
  • RWA Updates
    • doc (Using the _updateDoc helper or otherwise)
      • init the RwaLiquidationOracle to reset the doc
      • Sanity Check pip must be set (not the zero address)
      • ilk follows format "RWAXXX-A"
      • val price ignored (0) if init has already been called
      • doc new legal document (IPFS HASH) matches Doc (or Forum Post)
      • tau parameter used is the old tau value
    • Debt Ceiling changes (line)
      • Autoline (line) + Liquidation Oracle Price Bump (val)
        • Enable Autoline
          • ilk follows format "RWAXXX-A"
          • line (max debt ceiling)
          • gap
          • ttl
      • Debt Ceiling (line) + Liquidation Oracle Price Bump (val)
        • Increase Ilk Debt Ceiling (set DC + increase Global DC)
      • bump RwaLiquidationOracle with new computed increased price (val)
        • ensure val is set accordingly with autoline max debt ceiling (line)
        • val should enable DAI to be drawn over the loan period while taking into account the configured ink amount, interest rate and liquidation ratio (see below)
          • New val is calculated with line * [(1 + duty) ** years] * mat - rounded up - and makes sense in context of the rate mechanism. Minimum duration is usually in the Exec Doc of the spell with the RWAXXX ilk onboarding.
          • Comment explaining val formula (Debt ceiling * [ (1 + RWA stability fee ) ^ (minimum deal duration in years) ] * liquidation ratio) is present
          • Accompanying comment above bump line in format // XXM * 1.XX^X * X.XX as a WAD corresponding to the val calculation formula (e.g. // 15M * 1.03^2 * 1.00 as a WAD) is present along with the calculation formula on the line above
          • IF combining val of multiple RWA ilks being combined, val calculation is done once per ilk and added to make the total, with workings provided in code comments. The existing val value can be retrieved by calling read() on PIP_RWAXX and converting the result into decimal.
      • Poke spotter to pull in the new price
    • Soft Liquidation (tell)
      • Call RwaLiquidationOracle.tell(ilk)
      • IF RWAXX_A_INPUT_CONDUIT is an instance of TinlakeMgr (it is a Centrifuge integration)
        • Call TinlakeMgr.tell() to prevent further TIN redemptions in the Centrifuge pool.
  • Payments
    • Payments are not crafted or reviewed on Goerli (comments may be present)
  • SubDAO Content
    • SubDAO SubProxy spell execution
      • SubDAO spell address matches Exec Sheet (comment or otherwise)
      • 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
      • Executed using ProxyLike(SUBDAO_PROXY).exec(SUBDAO_SPELL, abi.encodeWithSignature("execute()"));
      • Execution is NOT delegate call
      • Reviewer Note: Gas cost may be very high as SubDAO spells execute within the main cast execution. (Also note that low level call gas estimation is not done by our scripts)
    • Maker Core (main spell) SubDAO actions (i.e. operate in 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 are verified (Blocking if not true)
      • Upgradable SubDAO contracts
        • Any 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 and addresses being called must be confirmed by the SubDAO spell team.
      • 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 Sheet 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)
  • External Contracts Calls (Not SubDAOs, e.g. Starknet)
    • Target Contract don't block spell execution
    • External call is NOT delegate call
    • 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
  • ChainLog
    • Increment ChainLog version 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.++)
  • addresses_goerli.sol matches spell code
  • Ensure every spell variable is declared as public/internal
  • Ensure every spell variable is used in the spell (no unused variables)
  • Spell actions match the corresponding Exec Sheet
  • Tests
    • Ensure each spell action has sufficient test coverage
      List actions for which coverage was checked here
      - Changes to the "Local Liquidation Limit"s
      - Are tested via testGeneral()
      - Changes to the "Global Liquidation Limit"
      - Is tested via testGeneral()
      - Updated of the RWA doc
      - Is tested via testRWA009DocChange
    • Ensure every test function is declared as public if enabled or private if disabled
      testIlkClipper is set to public, while not being needed in this spell. Please set it to private
    • 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
      2c61a6f
    • Check all tests are passing locally using make test
      • Ensure that only ETH_RPC_URL is being used from env (i.e. no match, block or similar are active in your env)
_Insert your passing local tests here_

./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x122F6c0Dcd898b4a07310E92c3eAE5D7Ce0c8bb6
[⠊] Compiling...
[⠔] Compiling 33 files with 0.8.16
[⠆] Solc 0.8.16 finished in 3.56s
Compiler run successful!
 
Running 17 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1885264)
[PASS] testCastCost() (gas: 496885)
[PASS] testChainlogIntegrity() (gas: 12971885)
[PASS] testChainlogValues() (gas: 8194473)
[PASS] testContractSize() (gas: 9007)
[PASS] testDeployCost() (gas: 1872228)
[PASS] testFailNotScheduled() (gas: 14398)
[PASS] testFailTooEarly() (gas: 13563)
[PASS] testFailTooLate() (gas: 13562)
[PASS] testFailWrongDay() (gas: 13563)
[PASS] testGeneral() (gas: 27231970)
[PASS] testIlkClipper() (gas: 1128502)
[PASS] testNextCastTime() (gas: 364857)
[PASS] testOnTime() (gas: 492569)
[PASS] testPSMs() (gas: 1848784)
[PASS] testRWA009DocChange() (gas: 549669)
[PASS] testUseEta() (gas: 363542)
Test result: ok. 17 passed; 0 failed; 0 skipped; finished in 891.81s

Running 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 646874)
[PASS] testStarknetSpell() (gas: 2302)
Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 891.81s

@0xp3th1um
Copy link
Collaborator

0xp3th1um commented Feb 5, 2024

Good to deploy!

Goerli Executive Spell Review Checklist

Goerli 2024-02-07

Spell Actions (Per Exec Sheet):

  • Read spell actions and instructions from the Exec Sheet
  • List the actions being performed in this spell

Auction Parameter Updates
Increase the WSTETH-A Local Liquidation Limit (ilk.hole) by 15 million DAI from 15 million DAI to 30 million DAI.
Increase the WSTETH-B Local Liquidation Limit (ilk.hole) by 10 million DAI from 10 million DAI to 20 million DAI.
Decrease the WBTC-A Local Liquidation Limit (ilk.hole) by 20 million DAI from 30 million DAI to 10 million DAI.
Decrease the WBTC-B Local Liquidation Limit (ilk.hole) by 5 million DAI from 10 million DAI to 5 million DAI.
Decrease the WBTC-C Local Liquidation Limit (ilk.hole) by 10 million DAI from 20 million DAI to 10 million DAI.

Increase the Global Liquidation Limit (Hole) by 50 million DAI from 100 million DAI to 150 million DAI.

Push GUSD out of input conduit
Raise PSM-GUSD-A DC to 597,660 DAI
Call push() on MCD_PSM_GUSD_A_INPUT_CONDUIT_JAR (use push(uint256 amt)) to push 597,659 GUSD
Call void() on MCD_PSM_GUSD_A_JAR
Set PSM-GUSD-A DC to 0 DAI

Aave SparkLend Revenue Share
Transfer 100,603 DAI to 0x464C71f6c2F760DdA6093dCB91C24c39e5d6e18c

RWA009 doc Update
Update HVBank (RWA009-A) doc to QmPzuLuJ5Xq6k6Hbop1W5s4V9ksvafYoqcW9sU5QRwz5h1

Delegate Compensation
0xDefensor - 41.67 MKR - 0x9542b441d65B6BF4dDdd3d4D2a66D8dCB9EE07a9
BLUE - 41.67 MKR - 0xb6C09680D822F162449cdFB8248a7D3FC26Ec9Bf
BONAPUBLICA - 41.67 MKR - 0x167c1a762B08D7e78dbF8f24e5C3f1Ab415021D3
Cloaky - 41.67 MKR - 0x869b6d5d8FA7f4FFdaCA4D23FFE0735c5eD1F818
TRUE NAME - 41.67 MKR - 0x612F7924c367575a0Edf21333D96b15F1B345A5d
PBG - 13.89 MKR - 0x8D4df847dB7FfE0B46AF084fE031F7691C6478c2
UPMaker - 13.89 MKR - 0xbB819DF169670DC71A16F58F55956FE642cc6BcD
vigilant - 13.89 MKR - 0x2474937cB55500601BCCE9f4cb0A0A72Dc226F61
WBC - 13.89 MKR - 0xeBcE83e491947aDB1396Ee7E55d3c81414fB0D47
JAG - 13.71 MKR - 0x58D1ec57E4294E4fe650D1CB12b96AE34349556f

Development Stage

  • Office Hours
    • OFF (On Goerli the deployed spell is cast with a pause delay of 60 sec.)
  • 30 days spell expiry in constructor (block.timestamp + 30 days)
  • No Exec Doc Hash on Goerli
  • Spell Description
    • Ensure description exactly matches 'Goerli Spell'
  • Ensure the comments inside the spell action are correct:
    • Every Section text from the Exec Sheet should be copied as comment to the spell code (above the code segment that implements the action)
      • is surrounded by the set of dashes (E.g. // ----- Section text -----)
    • Every Instruction text Exec Sheet should be:
      • copied to the spell code as // Instruction text
      • have newline above it
    • Every Reasoning URL and Authority URL from the Exec Sheet should be present under relevant section or instruction in the spell code (depending on which row the link is present)
      • Every Reasoning URL and Authority URL should 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/
    • If action in the spell doesn't have relevant instruction (e.g.: chainlog version bump), it should have explanation prefixed with // Note:
    • If an instruction can not be taken, it should have a comment under the instruction prefixed with // Note: (e.g.: // Note: Payments are skipped on goerli)
  • Local Environment Actions
    • Update Foundry by running foundryup
    • Reinstall libraries by running rm -r lib && git submodule update --init --recursive
      Submodule path 'lib/dss-exec-lib': checked out '69b658f35d8618272cd139dfc18c5713caf6b96b'
      Submodule path 'lib/dss-exec-lib/lib/dss-interfaces': checked out '9bfd7afadd1f8c217ef05850b2555691786286cb'
      Submodule path 'lib/dss-exec-lib/lib/forge-std': checked out '0aa99eb8456693c015350c5e6c4f442ebe912f77'
      Submodule path 'lib/dss-exec-lib/lib/forge-std/lib/ds-test': checked out 'cd98eff28324bfac652e63a239a60632a761790b'
      Submodule path 'lib/dss-test': checked out '36ff4adbcb35760614e0d2df864026991c23d028'
      Submodule path 'lib/dss-test/lib/dss-interfaces': checked out '9bfd7afadd1f8c217ef05850b2555691786286cb'
      Submodule path 'lib/dss-test/lib/forge-std': checked out '155d547c449afa8715f538d69454b83944117811'
      Submodule path 'lib/dss-test/lib/forge-std/lib/ds-test': checked out 'e282159d5170298eb2455a6c05280ab5a73a4ef0'
      
    • Library Checks
      • dss-exec-lib
        • If submodule upgrades are present make sure dss-exec-lib is synced as well
        • (Non-critical) Submodule hash matches the latest release version (NOTE: dss-exec-lib as installed locally will use GitHub code more recent than the 0.0.9 release until the 0.0.10 release)
      • dss-test
        ℹ️ Skipped
  • Rate constants used are correct
    • Manual check 1: Calculate rates using make rates pct=<pct> (e.g. pct=0.75, for 0.75%)
    • Manual check 2: Compare rates used against IPFS rate list
    • Variable name conforms to X_PT_Y_Z_PCT_RATE (e.g. ZERO_PT_SEVEN_FIVE_PCT_RATE for 0.75%, SIX_PCT_RATE for 6.00%)
    • Visibility is internal
    • State mutability is constant
  • Constants Match
    • Precision unit constants used match their defined values
      • WAD = 10 ** 18
      • RAY = 10 ** 27
      • RAD = 10 ** 45
      • Visibility is internal
      • State mutability is constant
      • (Non-critical) Ensure they match with ds-math and the Numerical Ranges
    • Math unit constants used match their defined values
      • HUNDRED = 10 ** 2
      • THOUSAND = 10 ** 3~~
      • MILLION = 10 ** 6
      • BILLION = 10 ** 9~~
      • Visibility is internal
      • State mutability is constant
      • (Non-critical) Ensure they match with config
  • Address Declaration
    • Address Constants
      • Address is not in the ChainLog
      • Variable name matches corresponding entry in an addresses.sol file
      • Address value matches corresponding entry in an addresses.sol file
      • Visibility is internal
      • State mutability is constant
    • Address Immutables
      • Use the DssExecLib Core Address Helpers instead of getChangelogAddress() whenever possible (e.g. DssExecLib.vat())
      • Follow pattern address internal immutable KEY_NAME = DssExecLib.getChangelogAddress(KEY_NAME)
      • Variable name matches ChainLog key name
        • Exceptions must follow archive patterns (e.g. MKR for MCD_GOV)
      • Instantiate as address type
        • Exceptions must follow archive patterns (e.g. GemLike for MKR)
      • Visibility is internal
      • State mutability is immutable
  • String Constants
    • IPFS hashes or DAO resolutions
      • IPFS hashes and DAO resolutions match the exec doc
      • The variable is named dao_resolutions
      • if multiple dao resolutions are present
        • they are located in the same string constant and are comma separated
        • The comment above the the variable states: Comma-separated list of DAO resolutions IPFS hashes
    • Must be TOP LEVEL (or ds pause will reject)
    • Name of the variable matches purpose per EXEC DOC
    • Visibility is public
    • State mutability MUST BE constant
  • Deployed Contracts (not yet on chainlog or new to chainlog)
    • Verified on etherscan
    • Optimizations match Repo
    • GNU AGPLv3 license
    • Constructor args ok (e.g. vat, dai, dog, ...)
    • Wards ok (pause proxy relied, deployer denied)
      • MCD_ESM is already relied / being relied in this spell (as approved by Governance Facilitators) in order to allow de-authing the pause proxy during Emergency Shutdown, via denyProxy.
    • Matches corresponding github source code (i.e. diffcheck via vscode code --diff etherscan.sol github.sol)
    • Ensure deployer address is included into addresses_deployers.sol (to keep up to date)
  • Core System Parameter Changes
  • Debt Ceiling Changes
  • Onboarding (insert relevant checklists inline here)
  • Offboarding (Lerp mat)
    • 1st Stage Spell Actions
      • Remove Ilk from Autoline
      • Set Ilks Debt Ceilings to 0
      • Cache Ilks line to Reduce in the Global Debt Ceiling
      • Decrease Global Debt Ceiling by Total Amount of Offboarded Ilks line Cached
    • 2nd Stage Spell Actions
      • Set Ilk Liquidation Penalty chop to 0
      • Set Keeper Incentive Flat Rate tip to 0
      • Check IF chip is required to be adjusted as well
      • Use DssExecLib.linearInterpolation
        • name Format matches "XXX-A Offboarding"
        • target matches spotter
        • ilk Format matches "XXX-A"
        • what matches mat
        • startTime matches block.timestamp
        • start matches Var CURRENT_XXX_A_MAT
        • end matches Var TARGET_XXX_A_MAT (Match Exec Sheet & Risk Computations)
          • Check IF Target mat Covers All Remaining Vaults CR times Risk Multiplier Factor
        • duration matches Exec Sheet
  • RWA Updates
    • doc (Using the _updateDoc helper or otherwise)
      • init the RwaLiquidationOracle to reset the doc
      • Sanity Check pip must be set (not the zero address)
      • ilk follows format "RWAXXX-A"
      • val price ignored (0) if init has already been called
      • doc new legal document (IPFS HASH) matches Doc (or Forum Post)
      • tau parameter used is the old tau value
    • Debt Ceiling changes (line)
      • Autoline (line) + Liquidation Oracle Price Bump (val)
        • Enable Autoline
          • ilk follows format "RWAXXX-A"
          • line (max debt ceiling)
          • gap
          • ttl
      • Debt Ceiling (line) + Liquidation Oracle Price Bump (val)
        • Increase Ilk Debt Ceiling (set DC + increase Global DC)
      • bump RwaLiquidationOracle with new computed increased price (val)
        • ensure val is set accordingly with autoline max debt ceiling (line)
        • val should enable DAI to be drawn over the loan period while taking into account the configured ink amount, interest rate and liquidation ratio (see below)
          • New valis calculated withline _ [(1 + duty) ** years] _ mat - rounded up - and makes sense in context of the rate mechanism. Minimum duration is usually in the Exec Doc of the spell with the RWAXXX ilk onboarding.
          • Comment explaining val formula (Debt ceiling _ [ (1 + RWA stability fee ) ^ (minimum deal duration in years) ] _ liquidation ratio) is present
          • Accompanying comment above bumpline in format// XXM _ 1.XX^X _ X.XX as a WADcorresponding to thevalcalculation formula (e.g.// 15M _ 1.03^2 _ 1.00 as a WAD) is present along with the calculation formula on the line above
          • IF combining valof multiple RWA ilks being combined,valcalculation is done once per ilk and added to make the total, with workings provided in code comments. The existingvalvalue can be retrieved by callingread()onPIP_RWAXX and converting the result into decimal.
      • Poke spotter to pull in the new price
    • Soft Liquidation (tell)
      • Call RwaLiquidationOracle.tell(ilk)
      • IF RWAXX_A_INPUT_CONDUIT is an instance of TinlakeMgr (it is a Centrifuge integration)
        • Call TinlakeMgr.tell() to prevent further TIN redemptions in the Centrifuge pool.
  • Payments
    • Payments are not crafted or reviewed on Goerli (comments may be present)
  • SubDAO Content
    • SubDAO SubProxy spell execution
      • SubDAO spell address matches Exec Sheet (comment or otherwise)
      • 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
      • Executed using ProxyLike(SUBDAO_PROXY).exec(SUBDAO_SPELL, abi.encodeWithSignature("execute()"));
      • Execution is NOT delegate call
      • Reviewer Note: Gas cost may be very high as SubDAO spells execute within the main cast execution. (Also note that low level call gas estimation is not done by our scripts)
    • Maker Core (main spell) SubDAO actions (i.e. operate in 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 are verified (Blocking if not true)
      • Upgradable SubDAO contracts
        • Any 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 and addresses being called must be confirmed by the SubDAO spell team.
      • 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 Sheet 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)
  • External Contracts Calls (Not SubDAOs, e.g. Starknet)
    • Target Contract don't block spell execution
    • External call is NOT delegate call
    • 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
  • ChainLog
    • Increment ChainLog version 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.++)
  • addresses_goerli.sol matches spell code
  • Ensure every spell variable is declared as public/internal
  • Ensure every spell variable is used in the spell (no unused variables)
  • Spell actions match the corresponding Exec Sheet
  • Tests
    • Ensure each spell action has sufficient test coverage
      List actions for which coverage was checked here
      [x] Auction Parameter Updates
      ✅ tested via testGeneral()
      [x] RWA009-A doc update
      ✅ tested by testRWA009DocChange()
    • Ensure every test function is declared as public if enabled or private if disabled
    • 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
      a2e8d93
    • Check all tests are passing locally using make test
      • Ensure that only ETH_RPC_URL is being used from env (i.e. no match, block or similar are active in your env)
_Insert your passing local tests here_
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x122F6c0Dcd898b4a07310E92c3eAE5D7Ce0c8bb6
[⠆] Compiling...
[⠃] Compiling 109 files with 0.8.16
[⠢] Solc 0.8.16 finished in 9.65s
Compiler run successful!

Running 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 646874)
[PASS] testStarknetSpell() (gas: 2302)
Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 177.32s

Running 17 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1885264)
[PASS] testCastCost() (gas: 496885)
[PASS] testChainlogIntegrity() (gas: 12971885)
[PASS] testChainlogValues() (gas: 8194473)
[PASS] testContractSize() (gas: 9007)
[PASS] testDeployCost() (gas: 1872228)
[PASS] testFailNotScheduled() (gas: 14398)
[PASS] testFailTooEarly() (gas: 13563)
[PASS] testFailTooLate() (gas: 13562)
[PASS] testFailWrongDay() (gas: 13563)
[PASS] testGeneral() (gas: 27231970)
[PASS] testIlkClipper() (gas: 1128502)
[PASS] testNextCastTime() (gas: 364857)
[PASS] testOnTime() (gas: 492569)
[PASS] testPSMs() (gas: 1848784)
[PASS] testRWA009DocChange() (gas: 549669)
[PASS] testUseEta() (gas: 363542)
Test result: ok. 17 passed; 0 failed; 0 skipped; finished in 662.28s

Ran 2 test suites: 19 tests passed, 0 failed, 0 skipped (19 total tests)

@SidestreamColdMelon
Copy link
Contributor

TLDR: Good to deploy

  • Aave SparkLend Revenue Share section fixed
  • Vote url added to the Auction Parameter Updates
  • testIlkClipper is now private
  • _updateDoc comment is matching the archive
  • No other changes were made
  • CI and local tests are ok
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x122F6c0Dcd898b4a07310E92c3eAE5D7Ce0c8bb6
[⠊] Compiling...
[⠃] Compiling 4 files with 0.8.16
[⠒] Solc 0.8.16 finished in 1.84s
Compiler run successful!

Running 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 646874)
[PASS] testStarknetSpell() (gas: 2302)
Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 135.54s

Running 16 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1885264)
[PASS] testCastCost() (gas: 496819)
[PASS] testChainlogIntegrity() (gas: 12971907)
[PASS] testChainlogValues() (gas: 8194495)
[PASS] testContractSize() (gas: 8940)
[PASS] testDeployCost() (gas: 1872250)
[PASS] testFailNotScheduled() (gas: 14420)
[PASS] testFailTooEarly() (gas: 13585)
[PASS] testFailTooLate() (gas: 13584)
[PASS] testFailWrongDay() (gas: 13585)
[PASS] testGeneral() (gas: 27231970)
[PASS] testNextCastTime() (gas: 364857)
[PASS] testOnTime() (gas: 492569)
[PASS] testPSMs() (gas: 1848801)
[PASS] testRWA009DocChange() (gas: 549624)
[PASS] testUseEta() (gas: 363475)
Test result: ok. 16 passed; 0 failed; 0 skipped; finished in 528.84s
 
Ran 2 test suites: 18 tests passed, 0 failed, 0 skipped (18 total tests)

@oddaf
Copy link
Member Author

oddaf commented Feb 6, 2024

@SidestreamColdMelon
Copy link
Contributor

TLDR: good to cast

Deployed Stage

  • Deployed Spell is Verified
    • Optimization Enabled: No
    • Other Settings: default evmVersion, GNU AGPLv3 license
  • Deployed Spell Code matches GitHub
    • diffcheck etherscan source against spell PR (via make diff-deployed-spell)
      ⚠️ The script didn't work, but manual check confirmed verified code on etherscan matches the source code
  • Deployed Spell Etherscan Checks
    • automated checks via make check-deployed-spell
      • verified
      • license type matches
      • solc version matches
      • optimizations are disabled
      • dss-exec-lib library address used (under 'Libraries Used') matches the hardcoded local DssExecLib.address file
        • Check again that the PR did not modify the DssExecLib.address file (e.g. look under the 'Files Changed' PR tab, etc.)
      • deployed_spell_created matches deployment timestamp
        ⚠️ The script says it doesn't match, but manual inspection confirms it's the same
      • deployed_spell_block matches deployment block number
        ⚠️ The script says it doesn't match, but manual inspection confirms it's the same
    • manual checks
      • Ensure make deploy-info tx=<tx> matches config
        • deployed_spell_created timestamp
        • deployed_spell_block block number
      • 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)
        ⚠️ Git submodule hash of the dss-exec-lib 69b658f35d8618272cd139dfc18c5713caf6b96b matches latest commit on the repo (from 2 years ago) not latest release. It's a known situation. Here is the diff between the latest release and the submodule hash: makerdao/dss-exec-lib@v0.0.9...69b658f
  • Archive matches src
    • make diff-archive-spell for current date or or date="YYYY-MM-DD" make diff-archive-spell (date as per cast timestamp)
    • Ensure date corresponds to target Exec Sheet 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
      bdaacb8
    • Check all tests are passing locally using make test
      • Ensure that only ETH_RPC_URL is being used from env (i.e. no match, block or similar are active in your env)
_Insert your passing local tests here_
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x122F6c0Dcd898b4a07310E92c3eAE5D7Ce0c8bb6
[⠒] Compiling...
[⠑] Compiling 4 files with 0.8.16
[⠔] Solc 0.8.16 finished in 2.10s
Compiler run successful!

Running 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 646874)
[PASS] testStarknetSpell() (gas: 2302)
Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 48.19s
 
Running 16 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1885264)
[PASS] testCastCost() (gas: 496819)
[PASS] testChainlogIntegrity() (gas: 12971907)
[PASS] testChainlogValues() (gas: 8194495)
[PASS] testContractSize() (gas: 8940)
[PASS] testDeployCost() (gas: 1872250)
[PASS] testFailNotScheduled() (gas: 14420)
[PASS] testFailTooEarly() (gas: 13585)
[PASS] testFailTooLate() (gas: 13584)
[PASS] testFailWrongDay() (gas: 13585)
[PASS] testGeneral() (gas: 27234067)
[PASS] testNextCastTime() (gas: 364857)
[PASS] testOnTime() (gas: 492569)
[PASS] testPSMs() (gas: 1848801)
[PASS] testRWA009DocChange() (gas: 549624)
[PASS] testUseEta() (gas: 363475)
Test result: ok. 16 passed; 0 failed; 0 skipped; finished in 528.86s
 
Ran 2 test suites: 18 tests passed, 0 failed, 0 skipped (18 total tests)

@0xp3th1um
Copy link
Collaborator

#TLDR: Good to cast!

Deployed Stage

  • Deployed Spell is Verified
    • Optimization Enabled: No
    • Other Settings: default evmVersion, GNU AGPLv3 license
  • Deployed Spell Code matches GitHub
    • diffcheck etherscan source against spell PR (via make diff-deployed-spell)
      ⚠️ Part of the verified code is different as in previous spells: part of the DssExecLib is replaced
  • Deployed Spell Etherscan Checks
    • automated checks via make check-deployed-spell
      • verified
      • license type matches
      • solc version matches
      • optimizations are disabled
      • dss-exec-lib library address used (under 'Libraries Used') matches the hardcoded local DssExecLib.address file
        • Check again that the PR did not modify the DssExecLib.address file (e.g. look under the 'Files Changed' PR tab, etc.)
      • deployed_spell_created matches deployment timestamp
        ⚠️ The script gives a wrong result on Mac, checked manually below
      • deployed_spell_block matches deployment block number
        ⚠️ The script gives a wrong result on Mac, checked manually below
    • manual checks
      • Ensure make deploy-info tx=<tx> matches config
        • deployed_spell_created timestamp
        • deployed_spell_block block number
      • 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)
        ℹ️ There is current mismatch as in previous spells.
  • Archive matches src
    • make diff-archive-spell for current date or or date="YYYY-MM-DD" make diff-archive-spell (date as per cast timestamp)
      ℹ️ There is a diff that can be ignored because the deployer address was added after the spell was archived
    • Ensure date corresponds to target Exec Sheet 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
      630e5d4
    • Check all tests are passing locally using make test
      • Ensure that only ETH_RPC_URL is being used from env (i.e. no match, block or similar are active in your env)
_Insert your passing local tests here_
./scripts/test-dssspell-forge.sh no-match="" match="" block=""
Using DssExecLib at: 0x122F6c0Dcd898b4a07310E92c3eAE5D7Ce0c8bb6
[⠃] Compiling...
[⠑] Compiling 6 files with 0.8.16
[⠊] Solc 0.8.16 finished in 4.87s
Compiler run successful!

Running 2 tests for src/test/starknet.t.sol:StarknetTests
[PASS] testStarknet() (gas: 646874)
[PASS] testStarknetSpell() (gas: 2302)
Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 41.80s

Running 16 tests for src/DssSpell.t.sol:DssSpellTest
[PASS] testBytecodeMatches() (gas: 1885264)
[PASS] testCastCost() (gas: 496819)
[PASS] testChainlogIntegrity() (gas: 12971907)
[PASS] testChainlogValues() (gas: 8194495)
[PASS] testContractSize() (gas: 8940)
[PASS] testDeployCost() (gas: 1872250)
[PASS] testFailNotScheduled() (gas: 14420)
[PASS] testFailTooEarly() (gas: 13585)
[PASS] testFailTooLate() (gas: 13584)
[PASS] testFailWrongDay() (gas: 13585)
[PASS] testGeneral() (gas: 27234067)
[PASS] testNextCastTime() (gas: 364857)
[PASS] testOnTime() (gas: 492569)
[PASS] testPSMs() (gas: 1848801)
[PASS] testRWA009DocChange() (gas: 549624)
[PASS] testUseEta() (gas: 363475)
Test result: ok. 16 passed; 0 failed; 0 skipped; finished in 471.74s

Ran 2 test suites: 18 tests passed, 0 failed, 0 skipped (18 total tests)

@oddaf
Copy link
Member Author

oddaf commented Feb 6, 2024

Spell was cast, tx 0x88cf905d57fffda49d3c4b8a0c9c33efd82eea9d2bad0e0b6d59a64f239e12b0

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.

Cast and Merge Stage

Copy link
Collaborator

@0xp3th1um 0xp3th1um left a comment

Choose a reason for hiding this comment

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

Cast and Merge Stage

  • Spell is Cast
    • Check Cast Trace (via EthTx)
      • Ensure no reverts are present that block execution
        • Inspect low level call reverts if expected
      • Ensure all actions are executed and no out-of-gas errors are present
  • Ensure that no commits or changes have occurred since the spell was deployed and archived
  • Approve spell PR for merge via 'Approve' review option

@oddaf oddaf merged commit 2db0206 into master Feb 7, 2024
3 checks passed
@amusingaxl amusingaxl deleted the 2024-02-07 branch February 7, 2024 15:26
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants