Skip to content

Conversation

@DaniPopes
Copy link
Member

@DaniPopes DaniPopes commented Sep 24, 2022

Motivation

closes: #3332

blocked by: gakonst/ethers-rs#1747 and #3395

Solution

  • cast storage <address> <slot>
  • cast storage <address>
    • compile as forge project
    • compile from etherscan sources
    • fetch address state
    • pretty print state

@DaniPopes DaniPopes marked this pull request as draft September 24, 2022 14:35
Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

this is great! tysm

some early suggestions :)

let match_code = |artifact: &ConfigurableContractArtifact| -> Option<bool> {
let bytes =
artifact.deployed_bytecode.as_ref()?.bytecode.as_ref()?.object.as_bytes()?;
Some(bytes == &address_code)
Copy link
Contributor

Choose a reason for hiding this comment

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

In the case of an external library, will the object be linked here? If it isn't then this match will always fail

// Get deployed bytecode at given address
let address_code = provider.get_code(address, block).await?;
if address_code.is_empty() {
eyre::bail!("Provided address has no deployed code and thus no storage");
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically if the contract selfdestructed, then it could have no code but have storage. I don't think there would be any way to get the storage reliably though, geth does have a RPC endpoint debug_storageRangeAt but its not part of the official json rpc spec

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, there's also parity_listStorageKeys, we could check if they are present and throw when they're not

@DaniPopes DaniPopes requested a review from mattsse October 14, 2022 17:04
@DaniPopes
Copy link
Member Author

DaniPopes commented Oct 18, 2022

I think this is almost done, just need a few things:

  • how to fetch and display array values, not mappings
  • how to format slot values (like forge?)
  • maybe a better way to fetch multiple storage slots' values concurrently
  • ignore test for non forking integration tests since it needs ETHERSCAN_API_KEY set

@mds1
Copy link
Collaborator

mds1 commented Nov 16, 2022

I've been using this branch to get the storage layout for deployed contracts, and it's been super helpful. Would love to get this PR out of draft and merged if possible! I think it's ok to to handle some of the above things in a future PR if they turn out to be a lot of work

@DaniPopes DaniPopes marked this pull request as ready for review November 16, 2022 16:57
@DaniPopes
Copy link
Member Author

@gakonst @mattsse bump

Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

this looks pretty good.

love the tests and example docs.

judging from the tests, this seems to be working.

smol nit, otherwise lgtm

let value = value?.into_uint();
let t = layout.types.get_mut(&slot.storage_type).expect("Bad storage");
// TODO: Better format values according to their Solidity type
t.value = Some(format!("{value:?}"));
Copy link
Member

Choose a reason for hiding this comment

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

can we pretty format here or is can we remove the TODO?

Copy link
Member Author

Choose a reason for hiding this comment

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

not sure how to format a H256 into solidity values. im assuming we already do this somewhere in forge when displaying traces

let auto_detect = version < MIN_SOLC;

// Create a new temp project
// TODO: Cache instead of using a temp directory: metadata from Etherscan won't change
Copy link
Member

Choose a reason for hiding this comment

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

this isn't very important and we shouldn't cache this in .foundry imo

Copy link
Member Author

@DaniPopes DaniPopes Nov 22, 2022

Choose a reason for hiding this comment

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

yeah its more so you dont have to download+compile every time when making multiple queries on the same address

@mattsse mattsse added T-feature Type: feature C-cast Command: cast labels Nov 22, 2022
});

// tests that the `cast storage` command works correctly
casttest!(cast_storage_succeeds, |_: TestProject, mut cmd: TestCommand| {
Copy link
Member

Choose a reason for hiding this comment

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

For some reason the etherscan key is not read here?

Copy link
Member Author

Choose a reason for hiding this comment

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

from what I'm seeing in other tests, they only run when the api key/private key env var is set (https://github.com/foundry-rs/foundry/blob/master/cli/tests/it/verify.rs)
and they're set only in the live tests

Copy link
Member

Choose a reason for hiding this comment

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

@mattsse let's bring the etherscan api key in scope here? Any reason not to?

Copy link
Member

Choose a reason for hiding this comment

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

don't think so, but unsure if the required key secrets are set. will check and enable

Copy link
Member

Choose a reason for hiding this comment

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

@mattsse when you get a chance, let's set the secrets here and merge

Copy link
Member

Choose a reason for hiding this comment

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

I don't think I've access to set secrets.

gakonst and others added 3 commits December 18, 2022 16:19
This reverts commit 3d16d55.

This was not the right fix as it triggered all integration tests to run.
@gakonst gakonst merged commit 18791df into foundry-rs:master Dec 18, 2022
@DaniPopes DaniPopes deleted the feat/cast-storage branch January 30, 2023 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-cast Command: cast T-feature Type: feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: cast storage modifications to print all state for an address

5 participants