Skip to content

Commit

Permalink
chore(anvil): migrate cheatsmanager to alloy (#6767)
Browse files Browse the repository at this point in the history
* chore: migrate cheatsmanager to alloy

* resolve nit

* merge
  • Loading branch information
Evalir authored Jan 12, 2024
1 parent 54f7733 commit 78b22db
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 16 deletions.
17 changes: 17 additions & 0 deletions crates/anvil/core/src/eth/transaction/ethers_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,23 @@ use ethers_core::types::{
};
use foundry_common::types::{ToAlloy, ToEthers};

pub fn to_alloy_signature(signature: ethers_core::types::Signature) -> alloy_rpc_types::Signature {
alloy_rpc_types::Signature {
r: signature.r.to_alloy(),
s: signature.s.to_alloy(),
v: signature.v.to_alloy().to::<rU256>(),
y_parity: None,
}
}

pub fn to_ethers_signature(signature: alloy_rpc_types::Signature) -> ethers_core::types::Signature {
ethers_core::types::Signature {
r: signature.r.to_ethers(),
s: signature.s.to_ethers(),
v: signature.v.to::<u64>(),
}
}

pub fn to_alloy_proof(proof: AccountProof) -> alloy_rpc_types::EIP1186AccountProofResponse {
alloy_rpc_types::EIP1186AccountProofResponse {
address: proof.address.to_alloy(),
Expand Down
13 changes: 9 additions & 4 deletions crates/anvil/core/src/eth/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,18 @@ use std::ops::Deref;
mod ethers_compat;

pub use ethers_compat::{
call_to_internal_tx_request, from_ethers_access_list, to_alloy_proof, to_ethers_access_list,
call_to_internal_tx_request, from_ethers_access_list, to_alloy_proof, to_alloy_signature,
to_ethers_access_list, to_ethers_signature,
};

/// The signature used to bypass signing via the `eth_sendUnsignedTransaction` cheat RPC
#[cfg(feature = "impersonated-tx")]
pub const IMPERSONATED_SIGNATURE: Signature =
Signature { r: U256([0, 0, 0, 0]), s: U256([0, 0, 0, 0]), v: 0 };
pub const IMPERSONATED_SIGNATURE: alloy_rpc_types::Signature = alloy_rpc_types::Signature {
r: alloy_primitives::U256::ZERO,
s: alloy_primitives::U256::ZERO,
v: alloy_primitives::U256::ZERO,
y_parity: None,
};

/// Container type for various Ethereum transaction requests
///
Expand Down Expand Up @@ -789,7 +794,7 @@ impl TypedTransaction {
/// Returns true if the transaction was impersonated (using the impersonate Signature)
#[cfg(feature = "impersonated-tx")]
pub fn is_impersonated(&self) -> bool {
self.signature() == IMPERSONATED_SIGNATURE
to_alloy_signature(self.signature()) == IMPERSONATED_SIGNATURE
}

/// Returns the hash if the transaction is impersonated (using a fake signature)
Expand Down
25 changes: 17 additions & 8 deletions crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ use anvil_core::{
eth::{
block::BlockInfo,
transaction::{
call_to_internal_tx_request, to_alloy_proof, EthTransactionRequest, LegacyTransaction,
PendingTransaction, TransactionKind, TypedTransaction, TypedTransactionRequest,
call_to_internal_tx_request, to_alloy_proof, to_ethers_signature,
EthTransactionRequest, LegacyTransaction, PendingTransaction, TransactionKind,
TypedTransaction, TypedTransactionRequest,
},
EthRequest,
},
Expand Down Expand Up @@ -564,9 +565,15 @@ impl EthApi {
pub fn accounts(&self) -> Result<Vec<Address>> {
node_info!("eth_accounts");
let mut unique = HashSet::new();
let mut accounts = Vec::new();
let mut accounts: Vec<Address> = Vec::new();
for signer in self.signers.iter() {
accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
accounts.extend(
signer
.accounts()
.into_iter()
.map(|a| a.to_alloy())
.filter(|acc| unique.insert(*acc)),
);
}
accounts.extend(
self.backend
Expand All @@ -575,7 +582,7 @@ impl EthApi {
.into_iter()
.filter(|acc| unique.insert(*acc)),
);
Ok(accounts.into_iter().map(|acc| acc.to_alloy()).collect())
Ok(accounts.into_iter().collect())
}

/// Returns the number of most recent block.
Expand Down Expand Up @@ -897,7 +904,8 @@ impl EthApi {
// if the sender is currently impersonated we need to "bypass" signing
let pending_transaction = if self.is_impersonated(from) {
let bypass_signature = self.backend.cheats().bypass_signature();
let transaction = sign::build_typed_transaction(request, bypass_signature)?;
let transaction =
sign::build_typed_transaction(request, to_ethers_signature(bypass_signature))?;
self.ensure_typed_transaction_supported(&transaction)?;
trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
PendingTransaction::with_impersonated(transaction, from.to_ethers())
Expand Down Expand Up @@ -1993,7 +2001,8 @@ impl EthApi {
let request = self.build_typed_tx_request(request, nonce)?;

let bypass_signature = self.backend.cheats().bypass_signature();
let transaction = sign::build_typed_transaction(request, bypass_signature)?;
let transaction =
sign::build_typed_transaction(request, to_ethers_signature(bypass_signature))?;

self.ensure_typed_transaction_supported(&transaction)?;

Expand Down Expand Up @@ -2528,7 +2537,7 @@ impl EthApi {

/// Returns true if the `addr` is currently impersonated
pub fn is_impersonated(&self, addr: Address) -> bool {
self.backend.cheats().is_impersonated(addr.to_ethers())
self.backend.cheats().is_impersonated(addr)
}

/// Returns the nonce of the `address` depending on the `block_number`
Expand Down
3 changes: 2 additions & 1 deletion crates/anvil/src/eth/backend/cheats.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Support for "cheat codes" / bypass functions

use alloy_primitives::Address;
use alloy_rpc_types::Signature;
use anvil_core::eth::transaction::IMPERSONATED_SIGNATURE;
use ethers::types::{Address, Signature};
use foundry_evm::hashbrown::HashSet;
use parking_lot::RwLock;
use std::sync::Arc;
Expand Down
6 changes: 3 additions & 3 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,20 +310,20 @@ impl Backend {
///
/// Returns `true` if the account is already impersonated
pub async fn impersonate(&self, addr: Address) -> DatabaseResult<bool> {
if self.cheats.impersonated_accounts().contains(&addr.to_ethers()) {
if self.cheats.impersonated_accounts().contains(&addr) {
return Ok(true);
}
// Ensure EIP-3607 is disabled
let mut env = self.env.write();
env.cfg.disable_eip3607 = true;
Ok(self.cheats.impersonate(addr.to_ethers()))
Ok(self.cheats.impersonate(addr))
}

/// Removes the account that from the impersonated set
///
/// If the impersonated `addr` is a contract then we also reset the code here
pub async fn stop_impersonating(&self, addr: Address) -> DatabaseResult<()> {
self.cheats.stop_impersonating(&addr.to_ethers());
self.cheats.stop_impersonating(&addr);
Ok(())
}

Expand Down

0 comments on commit 78b22db

Please sign in to comment.