2

In Brownie console, for a deployed contract, public contract attributes can be accessed with contract.nameOfAttribute(). This does not work for private attributes - how can one access private attribute values from the Brownie console? More generally, how does one dump the ongoing contract's state/storage from the Brownie console?

1 Answer 1

2
  • Here is the original code using web3.py
  • I have updated this version for 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)
        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)


display_storage("0x876807312079af775c49c916856A2D65f904e612")

If you get an error like this

ValueError: {'code': -32602, 'message': 'Errors encountered in param 1: Storage slot argument must have a length of 66 ("0x" + 32 bytes), but \'0x0\' has a length of 3', 'data': {'message': 'Errors encountered in param 1: Storage slot argument must have a length of 66 ("0x" + 32 bytes), but \'0x0\' has a length of 3'}}

  • You can fix this by modifying the value of i from int to 32 bytes hex str. Updated script.
#!/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")


  • Notice the value of i now changed to i.to_bytes(32, byteorder="big")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.