Skip to content

๐Ÿ” Protect your Smart Contract Proxy from storage collisions upon upgrading, by running this action in a CI on each of your Pull Requests!

Notifications You must be signed in to change notification settings

Rubilmax/foundry-storage-check

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

image

๐Ÿ”ฅ๐Ÿ› ๏ธ Foundry Storage Upgrade Seatbelt

  • Protect your Smart Contract Proxy from storage collisions upon upgrading, by running this action in a CI on each of your Pull Requests!
  • Feel safe when extending your storage layout by trusting this action to check that extended layout is zero-ed out on-chain!

Live Example

Check out PR #21 for a live example:

Getting started

Automatically generate & compare to the previous storage layout on every PR

Add a workflow (.github/workflows/foundry-storage-check.yml):

name: Check storage layout

on:
  push:
    branches:
      - main
  pull_request:
    # Optionally configure to run only for changes in specific files. For example:
    # paths:
    # - src/**
    # - test/**
    # - foundry.toml
    # - remappings.txt
    # - .github/workflows/foundry-storage-check.yml

jobs:
  check_storage_layout:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install Foundry
        uses: foundry-rs/[email protected]

      - name: Check storage layout
        uses: Rubilmax/[email protected]
        with:
          contract: src/Contract.sol:Contract
          # settings below are optional, but allows to check whether the added storage slots are empty on the deployed contract
          rpcUrl: wss://eth-mainnet.g.alchemy.com/v2/<YOUR_ALCHEMY_KEY> # the RPC url to use to query the deployed contract's storage slots
          address: 0x0000000000000000000000000000000000000000 # the address at which the contract check is deployed
          failOnRemoval: true # fail the CI when removing storage slots (default: false)

โ„น๏ธ An error will appear at first run!
๐Ÿ”ด Error: No workflow run found with an artifact named "..."
As the action is expecting a comparative file stored on the base branch and cannot find it (because the action never ran on the target branch and thus has never uploaded any storage layout)


How it works

Everytime somebody opens a Pull Request, the action runs Foundry forge to generate the storage layout of the Smart Contract you want to check.

Once generated, the action will fetch the comparative storage layout stored as an artifact from previous runs and compare them, to perform a series of checks at each storage byte, and raise a notice accordingly:

  • Variable changed: error
  • Type definition changed: error
  • Type definition removed: warning
  • Different variable naming: warning
  • Variable removed (optional): error

The action automatically checks for:

  • All canonic storage bytes
  • Array value (32 bytes) at index #0
  • Mapping value (32 bytes) at key 0x00
  • Zero-ed bytes for added storage variables

Options

contract {string}

The path and name of the contract of which to inspect storage layout (e.g. src/Contract.sol:Contract).

Required

address {string}

The address at which the contract is deployed on the EVM-compatible chain queried via rpcUrl.

rpcUrl {string}

The HTTP/WS url used to query the EVM-compatible chain for storage slots to check for clashing.

failOnRemoval {string}

Whether to fail the CI when removing a storage slot (to only allow added or renamed storage slots).

Defaults to: false

base {string}

The gas diff reference branch name, used to fetch the previous gas report to compare the freshly generated gas report to.

Defaults to: ${{ github.base_ref || github.ref_name }}

head {string}

The gas diff target branch name, used to upload the freshly generated gas report.

Defaults to: ${{ github.head_ref || github.ref_name }}

workingDirectory {string}

The directory inside which to run forge inspect.

Defaults to: .

retryDelay {string}

The retry delay (in milliseconds) between each GitHub API query.

Defaults to: 1000

token {string}

The github token allowing the action to upload and download gas reports generated by foundry. You should not need to customize this, as the action already has access to the default Github Action token.

Defaults to: ${{ github.token }}

This repository is maintained independently from Foundry and may not work as expected with all versions of forge.

About

๐Ÿ” Protect your Smart Contract Proxy from storage collisions upon upgrading, by running this action in a CI on each of your Pull Requests!

Topics

Resources

Stars

Watchers

Forks