Skip to content

Commit

Permalink
feat(cast): add support for beacon proxies in cast impl
Browse files Browse the repository at this point in the history
  • Loading branch information
0xvv committed Dec 17, 2024
1 parent 206dab2 commit 10c26f6
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 9 deletions.
13 changes: 10 additions & 3 deletions crates/cast/bin/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,8 @@ pub enum CastSubcommand {
formula_id: String,
},

/// Fetch the EIP-1967 implementation account
/// Fetch the EIP-1967 implementation for a contract
/// Can read from the implementation slot or the beacon slot.
#[command(visible_alias = "impl")]
Implementation {
/// The block height to query at.
Expand All @@ -615,7 +616,13 @@ pub enum CastSubcommand {
#[arg(long, short = 'B')]
block: Option<BlockId>,

/// The address to get the nonce for.
/// Fetch the implementation from the beacon slot.
///
/// If not specified, the implementation slot is used.
#[arg(long)]
beacon: bool,

/// The address for which the implementation will be fetched.
#[arg(value_parser = NameOrAddress::from_str)]
who: NameOrAddress,

Expand All @@ -632,7 +639,7 @@ pub enum CastSubcommand {
#[arg(long, short = 'B')]
block: Option<BlockId>,

/// The address to get the nonce for.
/// The address from which the admin account will be fetched.
#[arg(value_parser = NameOrAddress::from_str)]
who: NameOrAddress,

Expand Down
4 changes: 2 additions & 2 deletions crates/cast/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,11 @@ async fn main_args(args: CastArgs) -> Result<()> {
let id = stdin::unwrap_line(id)?;
sh_println!("{}", foundry_common::erc7201(&id))?;
}
CastSubcommand::Implementation { block, who, rpc } => {
CastSubcommand::Implementation { block, beacon, who, rpc } => {
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
let who = who.resolve(&provider).await?;
sh_println!("{}", Cast::new(provider).implementation(who, block).await?)?;
sh_println!("{}", Cast::new(provider).implementation(who, beacon, block).await?)?;
}
CastSubcommand::Admin { block, who, rpc } => {
let config = Config::from(&rpc);
Expand Down
27 changes: 23 additions & 4 deletions crates/cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,14 +571,33 @@ where
/// ProviderBuilder::<_, _, AnyNetwork>::default().on_builtin("http://localhost:8545").await?;
/// let cast = Cast::new(provider);
/// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
/// let implementation = cast.implementation(addr, None).await?;
/// let implementation = cast.implementation(addr, false, None).await?;
/// println!("{}", implementation);
/// # Ok(())
/// # }
/// ```
pub async fn implementation(&self, who: Address, block: Option<BlockId>) -> Result<String> {
let slot =
B256::from_str("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc")?;
pub async fn implementation(
&self,
who: Address,
is_beacon: bool,
block: Option<BlockId>,
) -> Result<String> {
let slot = match is_beacon {
true => {
// Use the beacon slot : bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)
B256::from_str(
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
)?
}
false => {
// Use the implementation slot :
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
B256::from_str(
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
)?
}
};

let value = self
.provider
.get_storage_at(who, slot.into())
Expand Down
36 changes: 36 additions & 0 deletions crates/cast/tests/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,42 @@ casttest!(rlp, |_prj, cmd| {
"#]]);
});

// test that `cast impl` works correctly for both the implementation slot and the beacon slot
casttest!(impl_slot, |_prj, cmd| {
let eth_rpc_url = next_http_rpc_endpoint();

// Call `cast impl` for the implementation slot (AAVE Proxy)
cmd.args([
"impl",
"0x4965f6FA20fE9728deCf5165016fc338a5a85aBF",
"--rpc-url",
eth_rpc_url.as_str(),
])
.assert_success()
.stdout_eq(str![[r#"
0xb61306c8eb34a2104d9eb8d84f1bb1001067fa4b
"#]]);
});

casttest!(impl_slot_beacon, |_prj, cmd| {
let eth_rpc_url = next_http_rpc_endpoint();

// Call `cast impl` for the beacon slot
cmd.args([
"impl",
"0xc63d9f0040d35f328274312fc8771a986fc4ba86",
"--beacon",
"--rpc-url",
eth_rpc_url.as_str(),
])
.assert_success()
.stdout_eq(str![[r#"
0xa748ae65ba11606492a9c57effa0d4b7be551ec2
"#]]);
});

// test for cast_rpc without arguments
casttest!(rpc_no_args, |_prj, cmd| {
let eth_rpc_url = next_http_rpc_endpoint();
Expand Down

0 comments on commit 10c26f6

Please sign in to comment.