Skip to content

Commit

Permalink
feat: add codehash and storage-root to cast (#8828)
Browse files Browse the repository at this point in the history
* feat: add codehash and storage-root to cast

* fix: use eth_getProof

* fix: nits
  • Loading branch information
Sabnock01 authored Sep 7, 2024
1 parent 27d008f commit 4d37740
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
42 changes: 42 additions & 0 deletions crates/cast/bin/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,48 @@ pub enum CastSubcommand {
rpc: RpcOpts,
},

/// Get the codehash for an account.
#[command()]
Codehash {
/// The block height to query at.
///
/// Can also be the tags earliest, finalized, safe, latest, or pending.
#[arg(long, short = 'B')]
block: Option<BlockId>,

/// The address to get the codehash for.
#[arg(value_parser = NameOrAddress::from_str)]
who: NameOrAddress,

/// The storage slot numbers (hex or decimal).
#[arg(value_parser = parse_slot)]
slots: Vec<B256>,

#[command(flatten)]
rpc: RpcOpts,
},

/// Get the storage root for an account.
#[command(visible_alias = "sr")]
StorageRoot {
/// The block height to query at.
///
/// Can also be the tags earliest, finalized, safe, latest, or pending.
#[arg(long, short = 'B')]
block: Option<BlockId>,

/// The address to get the storage root for.
#[arg(value_parser = NameOrAddress::from_str)]
who: NameOrAddress,

/// The storage slot numbers (hex or decimal).
#[arg(value_parser = parse_slot)]
slots: Vec<B256>,

#[command(flatten)]
rpc: RpcOpts,
},

/// Get the source code of a contract from Etherscan.
#[command(visible_aliases = &["et", "src"])]
EtherscanSource {
Expand Down
12 changes: 12 additions & 0 deletions crates/cast/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,18 @@ async fn main_args(args: CastArgs) -> Result<()> {
let who = who.resolve(&provider).await?;
println!("{}", Cast::new(provider).nonce(who, block).await?);
}
CastSubcommand::Codehash { block, who, slots, rpc } => {
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
let who = who.resolve(&provider).await?;
println!("{}", Cast::new(provider).codehash(who, slots, block).await?);
}
CastSubcommand::StorageRoot { block, who, slots, rpc } => {
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
let who = who.resolve(&provider).await?;
println!("{}", Cast::new(provider).storage_root(who, slots, block).await?);
}
CastSubcommand::Proof { address, slots, rpc, block } => {
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
Expand Down
66 changes: 66 additions & 0 deletions crates/cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,72 @@ where
Ok(self.provider.get_transaction_count(who).block_id(block.unwrap_or_default()).await?)
}

/// #Example
///
/// ```
/// use alloy_primitives::{Address, FixedBytes};
/// use alloy_provider::{network::AnyNetwork, ProviderBuilder, RootProvider};
/// use cast::Cast;
/// use std::str::FromStr;
///
/// # async fn foo() -> eyre::Result<()> {
/// let provider =
/// ProviderBuilder::<_, _, AnyNetwork>::default().on_builtin("http://localhost:8545").await?;
/// let cast = Cast::new(provider);
/// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
/// let slots = vec![FixedBytes::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")?];
/// let codehash = cast.codehash(addr, slots, None).await?;
/// println!("{}", codehash);
/// # Ok(())
/// # }
pub async fn codehash(
&self,
who: Address,
slots: Vec<B256>,
block: Option<BlockId>,
) -> Result<String> {
Ok(self
.provider
.get_proof(who, slots)
.block_id(block.unwrap_or_default())
.await?
.code_hash
.to_string())
}

/// #Example
///
/// ```
/// use alloy_primitives::{Address, FixedBytes};
/// use alloy_provider::{network::AnyNetwork, ProviderBuilder, RootProvider};
/// use cast::Cast;
/// use std::str::FromStr;
///
/// # async fn foo() -> eyre::Result<()> {
/// let provider =
/// ProviderBuilder::<_, _, AnyNetwork>::default().on_builtin("http://localhost:8545").await?;
/// let cast = Cast::new(provider);
/// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
/// let slots = vec![FixedBytes::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")?];
/// let storage_root = cast.storage_root(addr, slots, None).await?;
/// println!("{}", storage_root);
/// # Ok(())
/// # }
pub async fn storage_root(
&self,
who: Address,
slots: Vec<B256>,
block: Option<BlockId>,
) -> Result<String> {
Ok(self
.provider
.get_proof(who, slots)
.block_id(block.unwrap_or_default())
.await?
.storage_hash
.to_string())
}

/// # Example
///
/// ```
Expand Down

0 comments on commit 4d37740

Please sign in to comment.