Skip to content

Instantly share code, notes, and snippets.

@mikeshultz
Last active July 4, 2023 13:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeshultz/49c9844b948920f8204f164f70bf560a to your computer and use it in GitHub Desktop.
Save mikeshultz/49c9844b948920f8204f164f70bf560a to your computer and use it in GitHub Desktop.
Dump the non-zero storage of an Ethereum contract
"""
Blindly dumps the storage of an Ethereum contract
This dumps non-zero slots:
- range(0, height)
- range(keccak(slot), keccak(slot) + width)
This script makes no attempt to decode them past Python byte strings.
"""
import sys
from argparse import ArgumentParser
from hexbytes import HexBytes
from web3 import Web3, HTTPProvider
def parse_args(argv):
parser = ArgumentParser(description="Dump Ethereum contract storage.")
parser.add_argument(
"address", metavar="ADDRESS", type=str, nargs=1, help="contract address to dump"
)
parser.add_argument(
"-e", "--height", type=int, default=100, help="storage slots to cycle through"
)
parser.add_argument(
"-w",
"--width",
type=int,
default=100,
help="keccak(slot) + n storage slots to cycle through",
)
parser.add_argument(
"-p",
"--provider",
type=str,
default="http://localhost:8545",
help="Ethereum JSON-RPC provider",
)
return parser.parse_args()
def display_storage(web3, address, height=100, width=100):
for i in range(100):
# Regular slots
rs = web3.eth.get_storage_at(address, i)
if rs != HexBytes(
"0x0000000000000000000000000000000000000000000000000000000000000000"
):
print(i, rs)
# Slots for large values
slot = Web3.solidityKeccak(["uint256"], [i])
slot_int = int(slot.hex(), 16)
for j in range(100):
s = web3.eth.get_storage_at(address, slot_int + j)
if s != HexBytes(
"0x0000000000000000000000000000000000000000000000000000000000000000"
):
print(slot_int + j, s)
if __name__ == "__main__":
args = parse_args(sys.argv[1:])
web3 = Web3(HTTPProvider(args.provider))
display_storage(web3, args.address[0], args.height, args.width)
@Aviksaikat
Copy link

Aviksaikat commented Apr 18, 2023

Hi, Thanks for the code. I would like to add the updated version( Apr 2023) using brownie.

#!/usr/bin/python3
from brownie import web3
from hexbytes import HexBytes


def display_storage(address, height=100, width=100):
    for i in range(100):
        # Regular slots
        rs = web3.eth.get_storage_at(address, i.to_bytes(32, byteorder="big")).hex()
        if rs != "0x0000000000000000000000000000000000000000000000000000000000000000":
            print(i, rs)

        # Slots for large values
        slot = i.to_bytes(32, byteorder="big")
        slot_int = int.from_bytes(slot, byteorder="big")
        for j in range(100):
            s = web3.eth.get_storage_at(
                address, "0x" + hex(slot_int + j)[2:].zfill(64)
            ).hex()
            # print(s)
            if (
                s
                != "0x0000000000000000000000000000000000000000000000000000000000000000"
            ):
                print(i, s)


if __name__ == "__main__":
    display_storage("0x876807312079af775c49c916856A2D65f904e612")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment