HackMD
  • Prime
    Prime  Full-text search on all paid plans
    Search anywhere and reach everything in a Workspace with Prime plan.
    Got it
      • Create new note
      • Create a note from template
    • Prime  Full-text search on all paid plans
      Prime  Full-text search on all paid plans
      Search anywhere and reach everything in a Workspace with Prime plan.
      Got it
      • Options
      • Versions and GitHub Sync
      • Transfer ownership
      • Delete this note
      • Template
      • Save as template
      • Insert from template
      • Export
      • Dropbox
      • Google Drive
      • Gist
      • Import
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
      • Download
      • Markdown
      • HTML
      • Raw HTML
      • Sharing Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • More (Comment, Invitee)
      • Publishing
        Everyone on the web can find and read all notes of this public team.
        After the note is published, everyone on the web can find and read this note.
        See all published notes on profile page.
      • Commenting Enable
        Disabled Forbidden Owners Signed-in users Everyone
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Invitee
      • No invitee
    Menu Sharing Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Versions and GitHub Sync Transfer ownership Delete this note
    Export
    Dropbox Google Drive Gist
    Import
    Dropbox Google Drive Gist Clipboard
    Download
    Markdown HTML Raw HTML
    Back
    Sharing
    Sharing Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Note Permission
    Read
    Owners
    • Owners
    • Signed-in users
    • Everyone
    Owners Signed-in users Everyone
    Write
    Owners
    • Owners
    • Signed-in users
    • Everyone
    Owners Signed-in users Everyone
    More (Comment, Invitee)
    Publishing
    Everyone on the web can find and read all notes of this public team.
    After the note is published, everyone on the web can find and read this note.
    See all published notes on profile page.
    More (Comment, Invitee)
    Commenting Enable
    Disabled Forbidden Owners Signed-in users Everyone
    Permission
    Owners
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Invitee
    No invitee
       owned this note    owned this note      
    Published Linked with GitHub
    Like BookmarkBookmarked
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Auditing Executive Spells This is a guide to help MKR Holders verify executive spells in the Maker Protocol before voting for them. This document contains four main sections: 1. **Finding the Contract Code** - deals with locating the code for the executive in question. 2. **Validating Executive Code and Copy** - deals with ensuring that the spell and associated copy is as expected. 3. **Anatomy of a Spell Contract** - shows examples of the main sections you should expect to see in an executive spell. 4. **A Non-Exhaustive Checklist** - includes a list of the major things to double check and how to do so. The key approach when reviewing an executive spell is that if any part of an executive spell seems suspicious or confusing in any way it is always better to double check before voting. Even if you are mistaken in your concerns, this informs us to add more detail to this document to prevent someone becoming confused in the same way in the future. ## Finding the Contract Code The link to the spell on etherscan can be found on the voting portal in the 'Proposal details' pane. Look for the `Spell Address` property: ![](https://i.imgur.com/qdAfqZM.png) Clicking on the `Spell Address` will open the spell in Etherscan, where the viewer can click on the Contract tab to view the code: ![](https://i.imgur.com/vrIClir.png) The contract code should be visible. If it is only possible to see bytecode (meaning that the contract is unverified) then the executive should be viewed as potentially malicious. In this case, cry foul in chat and encourage people NOT to vote for it until the verified contract code is made available. Beyond looking in the [Governance Portal](www.vote.makerdao.com), current and past executive spell copy can also be found on [Github](https://github.com/makerdao/community/tree/master/governance/votes). ## Validating Spell Code Validate that the on-chain Etherscan code matches the corresponding [archive code](https://github.com/makerdao/spells-mainnet/tree/master/archive) or the most [recent executive](https://github.com/makerdao/spells-mainnet/tree/master/src) in Github. If it is not possible to locate the most recent spell, it may be because this has not been merged to the master branch before it goes live, in which case changes can be found in the pending [pull requests](https://github.com/makerdao/spells-mainnet/pulls). To do this code comparison, use a program called [Diff Checker](https://www.diffchecker.com/) to compare the Etherscan spell code against the relevant Github code. Clicking `find difference` will illustrate any differences between the two. Note, the Etherscan code will also illustrate interfaces to the DssExecLib, represented by the additional green section at the top of the file, which includes the following for awareness: ``` The following library code acts as an interface to the actual DssExecLib library, which can be found in its own deployed contract. Only trust the actual library's implementation. ``` This means that it is the DssExecLib [library](https://github.com/makerdao/spells-mainnet/tree/master/lib) itself that should be reviewed, and is something that will be covered in the following spell anatomy section. Otherwise, everything below this green text should be identical to the spell contents as presented in Github. ![](https://i.imgur.com/AaG6YDc.png) In the above example, the comparison is between this [Github file](https://github.com/makerdao/spells-mainnet/blob/master/archive/2021-09-24-DssSpell.sol) against the corresponding [Etherscan contract code](https://etherscan.io/address/0x0ed5a04DdE29f90bB00529608D3f17C1ffF778A0#code). ### Validating Governance Copy To ensure that the various actors (including governance facilitators, and smart contract developers) are aligned, the body of the spell includes a hash of the github copy that appears on the governance portal. This hash is included in the spell to confirm that the smart contract developers building the spell have referenced the correct copy being voted on. The hash appears in the spell in this manner: ``` "2021-09-24 MakerDAO Executive Spell | Hash: 0x655e71cb00b63a11c14db615d43d3e59202ff9d2b2bc6a6a03de42e258bd1be8"; ```` To validate that the governance portal copy on vote.makerdao.com which is reflected on [Github](https://github.com/makerdao/community/tree/master/governance/votes) has the same hash as is stored in the executive spell, the user can copy and paste the body of the gituhub text into this online [Github tool](https://emn178.github.io/online-tools/keccak_256.html) to generate and match the hash. Alternatively, the user can generate this hash run the following seth command: ``` seth keccak -- "$(wget https://raw.githubusercontent.com/makerdao/community/f33870a7938c1842e8467226f8007a2d47f9ddeb/governance/votes/Executive%20vote%20-%20October%208%2C%202021.md -q -O - 2>/dev/null)" ``` If the hash does not match, it would be prudent to question the spell contents and the copy that was referenced or changed. ## Anatomy of an Executive An executive spell is broken into a number of different parts, including; spell libraries, spell actions, and constructors, which will be reviewed below. ### Spell Library MakerDAO's executive spells have evolved over time towards using libraries in an effort to automate the process of making repetetive updates and changes to protocol parameters. Libraries reduce the chance of errors by reusing or building upon prior tested and verified code. In auditing the executive it is first necessary to check that the spell uses the dss-exec-lib library and secondly, that the library is the official and legitimate library. This can be confirmed by looking at the spell copy in Etherscan. The user can confirm that the executive is using the `dss-exec-lib` , by identifying the entry point for DssSpell is DssExec at the bottom of the contract code: ``` contract DssSpell is DssExec ``` It is then necessary to validate that the correct library is linked to and therefore importing the right code. By remaining on the etherscan contract tab, one can scroll to the bottom of the page and view the address of the DssExecLib: ![](https://i.imgur.com/OJfhqkr.png) To verify that DssExecLib is not malicious, the user can take the code block and compare it against a known repo, such as [makerdao/dss-exec-lib](https://github.com/makerdao/dss-exec-lib/tree/47bf15efe4cc9c737608c6acefb9de37fb3b3c7f) to validate any changes that may be present. Using Diff Checker is again useful for this purpose. It is also important to compare the address of the ExecLib from Etherscan against the Makerdao [Makefile](https://github.com/makerdao/spells-mainnet/blob/master/Makefile) and ensure that it matches the DssExecLib address: ![](https://i.imgur.com/NpVIocV.png) With the above matching, the user should be confident that the referenced library is indeed valid. ### Spell Constructor Now that the user is satisfied that the library is valid, it is possible to return to the spell and review the last line which reveals the DssExec constructor which determines the schedule and cast constraints: ``` { constructor() DssExec(block.timestamp + 30 days, address(new DssSpellAction())) public {} } ``` This line calls the constructor code inside the DssExec Library and passes it an expiration timestamp, so whenever this spell is created, it takes the current block timestamp and adds a number of days, in this case 30 days. This should align with Governance process. It is also necessary to ensure that this passes the above DssSpellAction code block which instantiates the spell. It is worth noting that although the constructor determines schedule and cast constraints, these variables have been abstracted away into the [ExecLib](https://github.com/makerdao/dss-exec-lib/blob/master/src/DssExec.sol), and no longer appear in the spell. After `schedule` has been called and after the delay is up, anyone can call `cast` which will execute the code in the SpellAction's `DssSpellActions` function, below. ### Spell Actions Now that there is confidence in the framework around the spell and the external library, it is possible to focus on Spell Actions, which is the bulk of what is getting scheduled and cast for execution. Users reviewing past spells may recall the use of the `execute` function. This is no longer used as Spell Actions are used to point to the ExecLib to make protocol changes. Again this highlights the importance of the library and a useful approach for reducing the size of spells. As a general rule, it is important to check everything in the section before or after the Spell Actions is a **constant**, as shown here for example: ``` contract DssSpellAction is DssAction { // Provides a descriptive tag for bot consumption // This should be modified weekly to provide a summary of the actions // Hash: seth keccak -- "$(wget https://raw.githubusercontent.com/makerdao/community/3d3670a98ca02e74c001bdf083765ab4eb4bc2cd/governance/votes/Executive%20vote%20-%20September%2024%2C%202021.md -q -O - 2>/dev/null)" string public constant override description = "2021-09-24 MakerDAO Executive Spell | Hash: 0x655e71cb00b63a11c14db615d43d3e59202ff9d2b2bc6a6a03de42e258bd1be8"; // L2 Test Spells address constant OPTIMISM_L1_GOVERNANCE_RELAY = 0x09B354CDA89203BB7B3131CC728dFa06ab09Ae2F; address constant OPTIMISM_L2_SPELL = 0x71d75C3D100D14d4db0cE7a83d0De48ecEC32D19; address constant ARBITRUM_L1_GOVERNANCE_RELAY = 0x9ba25c289e351779E0D481Ba37489317c34A899d; address constant ARBITRUM_L2_SPELL = 0xAeFc25750d8C2bd331293076E2DC5d5ad414b4a2; // Math uint256 constant MILLION = 10 ** 6; function actions() public override { ``` If any of these values are not constants, they could present malicious code in the form of memory mutations impacting the function of the pause proxy, and the community should be alerted. This risk is further covered below in the Constant Variables section. As mentioned in the library section above, standard actions will typically use DssExecLib calls to perform an action in a safe way. For non-standard actions, these will fall back to direct system calls. Some examples include: ``` function actions() public override { // Set ilk/global DC DssExecLib.increaseIlkDebtCeiling(collateral.ilk, collateral.CEIL, true); // Set stability fee DssExecLib.setIlkStabilityFee(collateral.ilk, collateral.RATE, false); // Set values directly Fileable(col.dog).file(col.ilk, "hole", col.hole); Fileable(col.dog).file(col.ilk, "chop", col.chop); Fileable(col.clipper).file("buf", col.buf); } ``` ### Office Hours The office hours function determines whether or not the spell, once voted in, is limited to being scheduled between 10:00 - 16:00 EST weekdays. Setting the value to true/false specifically enumerates whether it is applied or not. If this function is missing from the Spell Action, the code will fall back to the default office hours state there, which is true (office hours on) ``` function officeHours() public virtual returns (bool) { return true; ``` Such a value is `true` when new changes may impact integrators or auction keepers, and is otherwise `false` when office hours are not applied - meaning the spell can be cast at anypoint once successfully voted in. The code determining these rules has also been [abstracted](https://etherscan.io/address/0xfD88CeE74f7D78697775aBDAE53f9Da1559728E4#code#L335) away into the ExecLib. ## Non Exhaustive Checklist ### Verify that the contract code is visible Using the instructions above, find the contract code on Etherscan and ensure that it is visible and verified. Similarly ensure that the ExecLib is correctly referenced. verify that these match what the smart contract developers have published/deployed. ### Verify that the frontend copy matches the copy used to build the spell Create a hash of the github/frontend copy and reference this against the hash in the spell to confirm that the two align. ### Verify the constructor is as expected Ensure that the spell's expiry matches previous spells, includes the DssActions code block and that schedule and cast functions exist in DssExecLib. If the Constructor does not match previous functions, there should be an explanation as to why. ### Review the changelog Ensure that DssExecLib calls out to the changelog with the correct name descriptors. (these used to be spell addresses, but have since been replaced with name descriptors for simplicity and error reduction). It is therefore good practice to review the changelog to ensure that the correct name descriptor has been referenced as part of the on-chain action. ### Review oracle addresses Occasionally, there are spells involving Oracles - generally adding addresses to the whitelist, and occasionally adding a new oracle. These addresses must also be carefully verified. To do so it is necessary to go to the [Changelog](https://changelog.makerdao.com/) and look for e.g. `PIP_ETH`. Taking the contract to Etherscan and opening the contract `read` tab will display the `src` (listed as number 7 currently). The contract address listed there can be verified to match the `MedianETHUSDcontract` that is in the spell. ### Review rate changes Rates are defined as per-second accumulation values. These values can be validated against the commented rate by using the bc command in a bash shell. Using the `NEW_FEE ` variable in the example contract the following is visible: `bc -l <<< 'scale=27; e( l(1.095)/(60 * 60 * 24 * 365) )` This produces 1.000000002877801985002875644. Removing the decimal place will allow you to see that this matches the definition of `NEW_FEE`. Validating all rate adjustments can be done the same way. For more information on the rates module, please visit the [developer guides github](https://github.com/makerdao/developerguides/blob/master/mcd/intro-rate-mechanism/intro-rate-mechanism.md). For easy reference, common pre-computed rates can also be viewed at the following [ipfs link]( https://ipfs.io/ipfs/QmefQMseb3AiTapiAKKexdKHig8wroKuZbmLtPLv4u2YwW). ### Review DssExecLib to ensure Drip is called before rates are changed When making rate changes, `drip`must be called on the respective contracts. For example, if a DSR rate change is being made, `drip`is called on the `pot` or if the stability fee is being changed on a collateral type, it is necessary to call `drip("ILK")` on the `jug`. Despite `drip` being abstracted to the DssExecLib, it can still be confirmed in the library as part of the prior libary checks. To confirm this is possible, there is a boolean parameter `doDrip` in the execlib function. Users should ensure this is `true` to perform the drip, which can be found [here](https://github.com/makerdao/dss-exec-lib/blob/master/src/DssExecLib.sol#L777); ``` function setIlkStabilityFee(bytes32 _ilk, uint256 _rate, bool _doDrip) public { ``` ### All SpellAction contract variables must be declared 'constant' SpellActions must never have anything in contract memory. Therefore, all contract variables must be declared as constant. This is because at execution time, the contract's variables will be that of the DSPauseProxy. If there are variables in this section that are anything other than constant then it is a significant bug and must not be voted on.

    Import from clipboard

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lost their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template is not available.


    Upgrade

    All
    • All
    • Team
    No template found.

    Create custom template


    Upgrade

    Delete template

    Do you really want to delete this template?

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in via Google

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Tutorials

    Book Mode Tutorial

    Slide Mode Tutorial

    YAML Metadata

    Contacts

    Facebook

    Twitter

    Feedback

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions

    Versions and GitHub Sync

    Sign in to link this note to GitHub Learn more
    This note is not linked with GitHub Learn more
     
    Add badge Pull Push GitHub Link Settings
    Upgrade now

    Version named by    

    More Less
    • Edit
    • Delete

    Note content is identical to the latest version.
    Compare with
      Choose a version
      No search result
      Version not found

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub

        Please sign in to GitHub and install the HackMD app on your GitHub repo. Learn more

         Sign in to GitHub

        HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Available push count

        Upgrade

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Upgrade

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully