Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ffef79c
anvil-polkadot(impersonation): add impersonate...
iulianbarbu Sep 25, 2025
10a3388
anvil-polkadot(tests): add tracing support
iulianbarbu Sep 25, 2025
225672c
anvil-polkadot(misc): fix warnings
iulianbarbu Sep 25, 2025
0b86c79
anvil-polkadot: polish logging
iulianbarbu Sep 26, 2025
6017530
anvil-polkadot(impersonation): add impersonate...
iulianbarbu Sep 26, 2025
d29afb0
anvil-polkadot(impersonation): testing all impersonation RPCs
iulianbarbu Sep 26, 2025
14accf2
anvil-polkadot(impersonation): polish test
iulianbarbu Sep 29, 2025
106567b
anvil-polkadot: customize addr recovery in ReceiptExtractor
iulianbarbu Sep 30, 2025
69a8e92
anvil-polkadot: point to custom polkadot-sdk
iulianbarbu Sep 30, 2025
481a292
anvil-polkadot: fix impersonation test
iulianbarbu Sep 30, 2025
4fe4396
Cargo.lock: update to latest custom polkadot-sdk
iulianbarbu Sep 30, 2025
5a09b1a
anvil-polkadot: update ReceiptExtractor constructor usage
iulianbarbu Sep 30, 2025
e5ff766
anvil-polkadot(tests): refactor send_transaction
iulianbarbu Oct 1, 2025
bd5dae5
anvil-polkadot: fix comments and revert newlines
iulianbarbu Oct 1, 2025
31dcfd0
foundry-cli: revert change
iulianbarbu Oct 1, 2025
4e60394
Cargo.lock: fix unwanted crates updates
iulianbarbu Oct 1, 2025
affa8e5
anvil-polkadot(tests): assert tx failure when auto impersonation is f…
iulianbarbu Oct 1, 2025
61c25f0
anvil-polkadot: rename cheats manager to impersonation
iulianbarbu Oct 1, 2025
b4d4948
anvil-polkadot: cargo fmt fix
iulianbarbu Oct 1, 2025
bcc7555
anvil-polkadot: fix typo
iulianbarbu Oct 1, 2025
d37ae56
taplo: added config and formatted...
iulianbarbu Oct 1, 2025
53fc8d8
Update crates/anvil-polkadot/tests/it/utils.rs
iulianbarbu Oct 1, 2025
dcdf5c3
Update crates/anvil-polkadot/tests/it/mining.rs
iulianbarbu Oct 1, 2025
991d8c3
Cargo.toml: changed back to polkadot-sdk/master
iulianbarbu Oct 1, 2025
bcab3f9
anvil-polkadot: address feedback
iulianbarbu Oct 6, 2025
5d489e0
tomls: revert formatting
iulianbarbu Oct 6, 2025
6162666
taplo: remove config
iulianbarbu Oct 6, 2025
f9d868f
Merge branch 'master' into ib-add-impersonation
iulianbarbu Oct 7, 2025
6e34608
anvil-polkadot(tests): parameterize auto_impersonate test with rstest
iulianbarbu Oct 7, 2025
cac0a84
anvil-polkadot(toml): fix cargo.toml formatting
iulianbarbu Oct 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,847 changes: 1,555 additions & 1,292 deletions Cargo.lock

Large diffs are not rendered by default.

76 changes: 38 additions & 38 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
[workspace]
members = [
"benches/",
"crates/anvil/",
"crates/anvil-polkadot",
"crates/anvil-polkadot/substrate-runtime",
"crates/anvil/core/",
"crates/anvil/rpc/",
"crates/anvil/server/",
"crates/cast/",
"crates/cheatcodes/",
"crates/cheatcodes/spec/",
"crates/chisel/",
"crates/cli/",
"crates/common/",
"crates/config/",
"crates/debugger/",
"crates/doc/",
"crates/evm/core/",
"crates/evm/coverage/",
"crates/evm/evm/",
"crates/evm/fuzz/",
"crates/evm/traces/",
"crates/fmt/",
"crates/forge/",
"crates/script-sequence/",
"crates/macros/",
"crates/test-utils/",
"crates/revive-env",
"crates/revive-strategy",
"crates/lint/",
"benches/",
"crates/anvil/",
"crates/anvil-polkadot",
"crates/anvil-polkadot/substrate-runtime",
"crates/anvil/core/",
"crates/anvil/rpc/",
"crates/anvil/server/",
"crates/cast/",
"crates/cheatcodes/",
"crates/cheatcodes/spec/",
"crates/chisel/",
"crates/cli/",
"crates/common/",
"crates/config/",
"crates/debugger/",
"crates/doc/",
"crates/evm/core/",
"crates/evm/coverage/",
"crates/evm/evm/",
"crates/evm/fuzz/",
"crates/evm/traces/",
"crates/fmt/",
"crates/forge/",
"crates/script-sequence/",
"crates/macros/",
"crates/test-utils/",
"crates/revive-env",
"crates/revive-strategy",
"crates/lint/",
]
resolver = "2"

Expand Down Expand Up @@ -65,6 +65,7 @@ redundant_imports = "warn"
redundant-lifetimes = "warn"
rust-2018-idioms = "warn"
unused-must-use = "warn"
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(substrate_runtime)'] }
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

needed to supress some warnings after overriding the host functions

# unreachable-pub = "warn"

[workspace.lints.rustdoc]
Expand Down Expand Up @@ -254,10 +255,10 @@ alloy-op-hardforks = { version = "0.2.12", default-features = false }
alloy-dyn-abi = "1.2.1"
alloy-json-abi = "1.2.1"
alloy-primitives = { version = "1.2.1", features = [
"getrandom",
"rand",
"map-fxhash",
"map-foldhash",
"getrandom",
"rand",
"map-fxhash",
"map-foldhash",
] }
alloy-sol-macro-expander = "1.2.1"
alloy-sol-macro-input = "1.2.1"
Expand Down Expand Up @@ -308,8 +309,8 @@ walkdir = "2"
prettyplease = "0.2"
base64 = "0.22"
chrono = { version = "0.4", default-features = false, features = [
"clock",
"std",
"clock",
"std",
] }
axum = "0.8"
ciborium = "0.2"
Expand Down Expand Up @@ -337,8 +338,8 @@ rand_chacha = "0.9.0"
rayon = "1"
regex = { version = "1", default-features = false }
reqwest = { version = "0.12", default-features = false, features = [
"rustls-tls",
"rustls-tls-native-roots",
"rustls-tls",
"rustls-tls-native-roots",
] }
rustls = "0.23"
semver = "1"
Expand Down Expand Up @@ -367,7 +368,6 @@ uuid = "1.17.0"
flate2 = "1.1"



## Pinned dependencies. Enabled for the workspace in crates/test-utils.

# Use unicode-rs which has a smaller binary size than the default ICU4X as the IDNA backend, used
Expand Down
32 changes: 16 additions & 16 deletions crates/anvil-polkadot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ path = "bin/main.rs"
[dependencies]
# foundry internal
substrate-runtime = { path = "substrate-runtime" }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "master", default-features = false, features = [
"sc-allocator",
sp-runtime-interface = { git = "https://github.com/iulianbarbu/polkadot-sdk.git", branch = "ib-customize-addr-recovery", default-features = false }
secp256k1 = { version = "0.28.0", default-features = false }
libsecp256k1 = { version = "0.7.0", default-features = false }

polkadot-sdk = { git = "https://github.com/iulianbarbu/polkadot-sdk.git", branch = "ib-customize-addr-recovery", default-features = false, features = [
"sc-allocator",
"sc-basic-authorship",
"sc-block-builder",
"sc-chain-spec",
Expand All @@ -30,12 +34,12 @@ polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk.git", branch
"sc-client-db",
"sc-consensus",
"sc-consensus-manual-seal",
"sc-executor",
"sc-executor",
"sc-executor-common",
"sc-executor-wasmtime",
"sc-keystore",
"sc-network-types",
"sc-rpc",
"sc-rpc",
"sc-rpc-api",
"sc-rpc-server",
"sc-rpc-spec-v2",
Expand All @@ -53,11 +57,11 @@ polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk.git", branch
"sp-panic-handler",
"sp-rpc",
"std",
"substrate-frame-rpc-support",
"substrate-frame-rpc-support",
"substrate-frame-rpc-system",
"substrate-rpc-client",
"substrate-wasm-builder",
"pallet-revive-eth-rpc"
"pallet-revive-eth-rpc",
] }
anvil.workspace = true
anvil-core.workspace = true
Expand All @@ -81,11 +85,11 @@ alloy-dyn-abi = { workspace = true, features = ["std", "eip712"] }
alloy-rpc-types = { workspace = true, features = ["anvil", "trace", "txpool"] }
alloy-serde.workspace = true
alloy-provider = { workspace = true, features = [
"reqwest",
"ws",
"ipc",
"debug-api",
"trace-api",
"reqwest",
"ws",
"ipc",
"debug-api",
"trace-api",
] }
alloy-transport.workspace = true
alloy-chains.workspace = true
Expand Down Expand Up @@ -120,11 +124,7 @@ rand_08.workspace = true
eyre.workspace = true

# cli
clap = { version = "4", features = [
"derive",
"env",
"wrap_help",
] }
clap = { version = "4", features = ["derive", "env", "wrap_help"] }
clap_complete = { version = "4" }
chrono.workspace = true
clap_complete_fig = "4"
Expand Down
78 changes: 65 additions & 13 deletions crates/anvil-polkadot/src/api_server/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use crate::{
logging::LoggingManager,
macros::node_info,
substrate_node::{
in_mem_rpc::InMemoryRpcClient, mining_engine::MiningEngine, service::Service,
cheats::CheatsManager, in_mem_rpc::InMemoryRpcClient, mining_engine::MiningEngine,
service::Service,
},
};
use alloy_eips::{BlockId, BlockNumberOrTag};
Expand All @@ -20,7 +21,7 @@ use anvil_core::eth::{EthRequest, Params as MineParams};
use anvil_rpc::response::ResponseResult;
use futures::{StreamExt, channel::mpsc};
use polkadot_sdk::{
pallet_revive::evm::{Account, Block, Bytes, ReceiptInfo},
pallet_revive::evm::{Account, Block, Bytes, ReceiptInfo, TransactionSigned},
pallet_revive_eth_rpc::{
EthRpcError, ReceiptExtractor, ReceiptProvider, SubxtBlockInfoProvider,
client::{Client as EthRpcClient, ClientError, SubscriptionType},
Expand All @@ -45,6 +46,7 @@ pub struct ApiServer {
mining_engine: Arc<MiningEngine>,
eth_rpc_client: EthRpcClient,
wallet: Wallet,
cheats_manager: CheatsManager,
}

impl ApiServer {
Expand All @@ -60,6 +62,7 @@ impl ApiServer {
logging_manager,
mining_engine: substrate_service.mining_engine.clone(),
eth_rpc_client,
cheats_manager: CheatsManager::default(),
wallet: Wallet {
accounts: vec![
Account::from(subxt_signer::eth::dev::baltathar()),
Expand Down Expand Up @@ -128,6 +131,16 @@ impl ApiServer {
EthRequest::EthSendTransaction(request) => {
self.send_transaction(*request.clone()).await.to_rpc_result()
}
// -- Impersonation --
EthRequest::ImpersonateAccount(addr) => {
self.impersonate_account(H160::from_slice(addr.0.as_ref())).to_rpc_result()
}
EthRequest::StopImpersonatingAccount(addr) => {
self.stop_impersonating_account(&H160::from_slice(addr.0.as_ref())).to_rpc_result()
}
EthRequest::AutoImpersonateAccount(enable) => {
self.auto_impersonate_account(enable).to_rpc_result()
}
_ => Err::<(), _>(Error::RpcUnimplemented).to_rpc_result(),
};

Expand Down Expand Up @@ -369,13 +382,6 @@ impl ApiServer {
return Err(Error::ReviveRpc(EthRpcError::InvalidTransaction));
};

let account = self
.wallet
.accounts
.iter()
.find(|account| account.address() == from)
.ok_or(Error::ReviveRpc(EthRpcError::AccountNotFound(from)))?;

if transaction.gas.is_none() {
transaction.gas = Some(self.estimate_gas(transaction_req.clone(), None).await?);
}
Expand All @@ -396,7 +402,21 @@ impl ApiServer {
let tx = transaction
.try_into_unsigned()
.map_err(|_| Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
let payload = account.sign_transaction(tx).signed_payload();

let payload = if self.cheats_manager.is_impersonated(from) {
let mut fake_signature = [0; 65];
fake_signature[12..32].copy_from_slice(from.as_bytes());
tx.with_signature(fake_signature).signed_payload()
} else {
let account = self
.wallet
.accounts
.iter()
.find(|account| account.address() == from)
.ok_or(Error::ReviveRpc(EthRpcError::AccountNotFound(from)))?;
account.sign_transaction(tx).signed_payload()
};

self.send_raw_transaction(Bytes(payload)).await
}

Expand All @@ -407,6 +427,24 @@ impl ApiServer {
.await
.map_err(Error::from)
}

fn impersonate_account(&self, addr: H160) -> Result<()> {
node_info!("anvil_impersonateAccount");
self.cheats_manager.impersonate(addr);
Ok(())
}

fn auto_impersonate_account(&self, enable: bool) -> Result<()> {
node_info!("anvil_autoImpersonateAccount");
self.cheats_manager.set_auto_impersonate_account(enable);
Ok(())
}

fn stop_impersonating_account(&self, addr: &H160) -> Result<()> {
node_info!("anvil_stopImpersonatingAccount");
self.cheats_manager.stop_impersonating(addr);
Ok(())
}
}

async fn create_revive_rpc_client(substrate_service: &Service) -> Result<EthRpcClient> {
Expand All @@ -431,9 +469,22 @@ async fn create_revive_rpc_client(substrate_service: &Service) -> Result<EthRpcC
(pool, Some(100))
};

let receipt_extractor = ReceiptExtractor::new(api.clone(), None)
.await
.map_err(|err| Error::ReviveRpc(EthRpcError::ClientError(err)))?;
let receipt_extractor = ReceiptExtractor::new(
api.clone(),
None,
Some(Arc::new(|signed_tx: &TransactionSigned| {
let sig = signed_tx.raw_signature()?;
if sig[..12] == [0; 12] && sig[32..64] == [0; 32] {
let mut res = [0; 20];
res.copy_from_slice(&sig[12..32]);
Ok(H160::from(res))
} else {
signed_tx.recover_eth_address()
}
})),
)
.await
.map_err(|err| Error::ReviveRpc(EthRpcError::ClientError(err)))?;

let receipt_provider = ReceiptProvider::new(
pool,
Expand All @@ -459,5 +510,6 @@ async fn create_revive_rpc_client(substrate_service: &Service) -> Result<EthRpcC
panic!("Block subscription task failed: {err:?}",)
}
});

Ok(eth_rpc_client)
}
2 changes: 1 addition & 1 deletion crates/anvil-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub async fn spawn_anvil_tasks(
Ok(api_handle)
}

fn init_tracing(silent: bool) -> LoggingManager {
pub fn init_tracing(silent: bool) -> LoggingManager {
use tracing_subscriber::prelude::*;

let manager = LoggingManager::default();
Expand Down
Loading
Loading