Skip to content

Commit

Permalink
fix(cast): reset env.tx.caller for impersonated txs (#9544)
Browse files Browse the repository at this point in the history
* fix(`cast`): reset `env.tx.caller` for impersonated txs

* test
  • Loading branch information
yash-atreya authored Dec 12, 2024
1 parent 539760c commit 2eec098
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
14 changes: 13 additions & 1 deletion crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use foundry_cli::{
opts::{EtherscanOpts, RpcOpts},
utils::{handle_traces, init_progress, TraceResult},
};
use foundry_common::{is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE};
use foundry_common::{is_impersonated_tx, is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE};
use foundry_compilers::artifacts::EvmVersion;
use foundry_config::{
figment::{
Expand Down Expand Up @@ -212,6 +212,12 @@ impl RunArgs {

configure_tx_env(&mut env, &tx.inner);

if is_impersonated_tx(&tx.inner.inner) {
// If the transaction is impersonated, we need to set the caller to the from
// address Ref: https://github.com/foundry-rs/foundry/issues/9541
env.tx.caller = tx.from;
}

if let Some(to) = Transaction::to(tx) {
trace!(tx=?tx.tx_hash(),?to, "executing previous call transaction");
executor.transact_with_env(env.clone()).wrap_err_with(|| {
Expand Down Expand Up @@ -251,6 +257,12 @@ impl RunArgs {

configure_tx_env(&mut env, &tx.inner);

if is_impersonated_tx(&tx.inner.inner) {
// If the transaction is impersonated, we need to set the caller to the from address
// Ref: https://github.com/foundry-rs/foundry/issues/9541
env.tx.caller = tx.from;
}

if let Some(to) = Transaction::to(&tx) {
trace!(tx=?tx.tx_hash(), to=?to, "executing call transaction");
TraceResult::try_from(executor.transact_with_env(env))?
Expand Down
41 changes: 38 additions & 3 deletions crates/cast/tests/cli/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Contains various tests for checking cast commands
use alloy_chains::NamedChain;
use alloy_network::TransactionResponse;
use alloy_primitives::{b256, B256};
use alloy_rpc_types::{BlockNumberOrTag, Index};
use alloy_network::{TransactionBuilder, TransactionResponse};
use alloy_primitives::{address, b256, Bytes, B256};
use alloy_provider::{Provider, ProviderBuilder};
use alloy_rpc_types::{BlockNumberOrTag, Index, TransactionRequest};
use anvil::{EthereumHardfork, NodeConfig};
use foundry_test_utils::{
casttest, file, forgetest, forgetest_async,
Expand Down Expand Up @@ -1995,3 +1996,37 @@ forgetest_async!(cast_call_custom_chain_id, |_prj, cmd| {
])
.assert_success();
});

// https://github.com/foundry-rs/foundry/issues/9541
forgetest_async!(cast_run_impersonated_tx, |_prj, cmd| {
let (_api, handle) = anvil::spawn(
NodeConfig::test()
.with_auto_impersonate(true)
.with_eth_rpc_url(Some("https://sepolia.base.org")),
)
.await;

let http_endpoint = handle.http_endpoint();

let provider = ProviderBuilder::new().on_http(http_endpoint.parse().unwrap());

// send impersonated tx
let tx = TransactionRequest::default()
.with_from(address!("041563c07028Fc89106788185763Fc73028e8511"))
.with_to(address!("F38aA5909D89F5d98fCeA857e708F6a6033f6CF8"))
.with_input(
Bytes::from_str(
"0x60fe47b1000000000000000000000000000000000000000000000000000000000000000c",
)
.unwrap(),
);

let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();

assert!(receipt.status());

// run impersonated tx
cmd.cast_fuse()
.args(["run", &receipt.transaction_hash.to_string(), "--rpc-url", &http_endpoint])
.assert_success();
});
23 changes: 22 additions & 1 deletion crates/common/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Commonly used constants.
use alloy_primitives::{address, Address};
use alloy_consensus::Typed2718;
use alloy_network::AnyTxEnvelope;
use alloy_primitives::{address, Address, PrimitiveSignature, B256};
use std::time::Duration;

/// The dev chain-id, inherited from hardhat
Expand Down Expand Up @@ -53,6 +55,25 @@ pub fn is_known_system_sender(sender: Address) -> bool {
[ARBITRUM_SENDER, OPTIMISM_SYSTEM_ADDRESS].contains(&sender)
}

pub fn is_impersonated_tx(tx: &AnyTxEnvelope) -> bool {
if let AnyTxEnvelope::Ethereum(tx) = tx {
return is_impersonated_sig(tx.signature(), tx.ty());
}
false
}

pub fn is_impersonated_sig(sig: &PrimitiveSignature, ty: u8) -> bool {
let impersonated_sig = PrimitiveSignature::from_scalars_and_parity(
B256::with_last_byte(1),
B256::with_last_byte(1),
false,
);
if ty != SYSTEM_TRANSACTION_TYPE && sig == &impersonated_sig {
return true;
}
false
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 2eec098

Please sign in to comment.