Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cast): cast wallet & cast run alloy migration #7088

Merged
merged 11 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/cast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ alloy-dyn-abi.workspace = true
alloy-json-abi.workspace = true
alloy-primitives.workspace = true
alloy-rlp.workspace = true
alloy-providers.workspace = true
alloy-rpc-types.workspace = true
alloy-signer.workspace = true

ethers-core.workspace = true
ethers-providers.workspace = true
Expand Down
60 changes: 34 additions & 26 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use alloy_primitives::U256;
use alloy_providers::provider::TempProvider;
use alloy_rpc_types::BlockTransactions;
use clap::Parser;
use ethers_providers::Middleware;
use eyre::{Result, WrapErr};
use foundry_cli::{
init_progress,
opts::RpcOpts,
update_progress, utils,
update_progress,
utils::{handle_traces, TraceResult},
};
use foundry_common::{is_known_system_sender, types::ToAlloy, SYSTEM_TRANSACTION_TYPE};
use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE};
use foundry_compilers::EvmVersion;
use foundry_config::{find_project_root_path, Config};
use foundry_evm::{
Expand Down Expand Up @@ -87,19 +88,21 @@ impl RunArgs {
let compute_units_per_second =
if self.no_rate_limit { Some(u64::MAX) } else { self.compute_units_per_second };

let provider = utils::get_provider_builder(&config)?
.compute_units_per_second_opt(compute_units_per_second)
.build()?;
let provider = foundry_common::provider::alloy::ProviderBuilder::new(
&config.get_rpc_url_or_localhost_http()?,
)
.compute_units_per_second_opt(compute_units_per_second)
.build()?;

let tx_hash = self.tx_hash.parse().wrap_err("invalid tx hash")?;
let tx = provider
.get_transaction(tx_hash)
.await?
.ok_or_else(|| eyre::eyre!("tx not found: {:?}", tx_hash))?;
.get_transaction_by_hash(tx_hash)
.await
.wrap_err_with(|| format!("tx not found: {:?}", tx_hash))?;

// check if the tx is a system transaction
if is_known_system_sender(tx.from.to_alloy()) ||
tx.transaction_type.map(|ty| ty.as_u64()) == Some(SYSTEM_TRANSACTION_TYPE)
if is_known_system_sender(tx.from) ||
tx.transaction_type.map(|ty| ty.to::<u64>()) == Some(SYSTEM_TRANSACTION_TYPE)
{
return Err(eyre::eyre!(
"{:?} is a system transaction.\nReplaying system transactions is currently not supported.",
Expand All @@ -110,7 +113,7 @@ impl RunArgs {
let tx_block_number = tx
.block_number
.ok_or_else(|| eyre::eyre!("tx may still be pending: {:?}", tx_hash))?
.as_u64();
.to::<u64>();

// we need to fork off the parent block
config.fork_block_number = Some(tx_block_number - 1);
Expand All @@ -122,14 +125,14 @@ impl RunArgs {

env.block.number = U256::from(tx_block_number);

let block = provider.get_block_with_txs(tx_block_number).await?;
let block = provider.get_block(tx_block_number.into(), true).await?;
Evalir marked this conversation as resolved.
Show resolved Hide resolved
if let Some(ref block) = block {
env.block.timestamp = block.timestamp.to_alloy();
env.block.coinbase = block.author.unwrap_or_default().to_alloy();
env.block.difficulty = block.difficulty.to_alloy();
env.block.prevrandao = Some(block.mix_hash.map(|h| h.to_alloy()).unwrap_or_default());
env.block.basefee = block.base_fee_per_gas.unwrap_or_default().to_alloy();
env.block.gas_limit = block.gas_limit.to_alloy();
env.block.timestamp = block.header.timestamp;
env.block.coinbase = block.header.miner;
env.block.difficulty = block.header.difficulty;
env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default());
env.block.basefee = block.header.base_fee_per_gas.unwrap_or_default();
env.block.gas_limit = block.header.gas_limit;
}

// Set the state to the moment right before the transaction
Expand All @@ -140,11 +143,16 @@ impl RunArgs {
let pb = init_progress!(block.transactions, "tx");
pb.set_position(0);

for (index, tx) in block.transactions.into_iter().enumerate() {
// System transactions such as on L2s don't contain any pricing info so we skip
// them otherwise this would cause reverts
if is_known_system_sender(tx.from.to_alloy()) ||
tx.transaction_type.map(|ty| ty.as_u64()) ==
let BlockTransactions::Full(txs) = block.transactions else {
return Err(eyre::eyre!("Could not get block txs"))
};

for (index, tx) in txs.into_iter().enumerate() {
// System transactions such as on L2s don't contain any pricing info so
// we skip them otherwise this would cause
// reverts
if is_known_system_sender(tx.from) ||
tx.transaction_type.map(|ty| ty.to::<u64>()) ==
Some(SYSTEM_TRANSACTION_TYPE)
{
update_progress!(pb, index);
Expand All @@ -154,7 +162,7 @@ impl RunArgs {
break;
}

configure_tx_env(&mut env, &tx.clone().to_alloy());
configure_tx_env(&mut env, &tx);

if let Some(to) = tx.to {
trace!(tx=?tx.hash,?to, "executing previous call transaction");
Expand Down Expand Up @@ -191,7 +199,7 @@ impl RunArgs {
let result = {
executor.set_trace_printer(self.trace_printer);

configure_tx_env(&mut env, &tx.clone().to_alloy());
configure_tx_env(&mut env, &tx);

if let Some(to) = tx.to {
trace!(tx=?tx.hash, to=?to, "executing call transaction");
Expand Down
56 changes: 24 additions & 32 deletions crates/cast/bin/cmd/wallet/mod.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
use alloy_primitives::Address;
use clap::Parser;
use ethers_core::{
rand::thread_rng,
types::{transaction::eip712::TypedData, Signature},
};
use ethers_signers::{
use alloy_primitives::{Address, Signature, B256};
use alloy_signer::{
coins_bip39::{English, Mnemonic},
LocalWallet, MnemonicBuilder, Signer,
LocalWallet, MnemonicBuilder, Signer as AlloySigner,
};
use clap::Parser;
use ethers_core::types::transaction::eip712::TypedData;
use ethers_signers::Signer;
use eyre::{Context, Result};
use foundry_common::{
fs,
types::{ToAlloy, ToEthers},
};
use foundry_common::{fs, types::ToAlloy};
use foundry_config::Config;
use foundry_wallets::{RawWallet, Wallet};
use rand::thread_rng;
use serde_json::json;
use std::path::Path;
use std::{path::Path, str::FromStr};
use yansi::Paint;

pub mod vanity;
Expand Down Expand Up @@ -178,7 +174,7 @@ impl WalletSubcommands {

if let Some(json) = json_values.as_mut() {
json.push(json!({
"address": wallet.address().to_alloy().to_checksum(None),
"address": wallet.address().to_checksum(None),
"path": format!("{}", path.join(uuid).display()),
}
));
Expand All @@ -187,7 +183,7 @@ impl WalletSubcommands {
"Created new encrypted keystore file: {}",
path.join(uuid).display()
);
println!("Address: {}", wallet.address().to_alloy().to_checksum(None));
println!("Address: {}", wallet.address().to_checksum(None));
}
}

Expand All @@ -196,19 +192,16 @@ impl WalletSubcommands {
}
} else {
for _ in 0..number {
let wallet = LocalWallet::new(&mut rng);
let wallet = LocalWallet::random_with(&mut rng);

if let Some(json) = json_values.as_mut() {
json.push(json!({
"address": wallet.address().to_alloy().to_checksum(None),
"address": wallet.address().to_checksum(None),
"private_key": format!("0x{}", hex::encode(wallet.signer().to_bytes())),
}))
} else {
println!("Successfully created new keypair.");
println!(
"Address: {}",
wallet.address().to_alloy().to_checksum(None)
);
println!("Address: {}", wallet.address().to_checksum(None));
println!("Private key: 0x{}", hex::encode(wallet.signer().to_bytes()));
}
}
Expand All @@ -225,7 +218,7 @@ impl WalletSubcommands {
let builder = MnemonicBuilder::<English>::default().phrase(phrase.as_str());
let derivation_path = "m/44'/60'/0'/0/";
let wallets = (0..accounts)
.map(|i| builder.clone().derivation_path(&format!("{derivation_path}{i}")))
.map(|i| builder.clone().derivation_path(format!("{derivation_path}{i}")))
.collect::<Result<Vec<_>, _>>()?;
let wallets =
wallets.into_iter().map(|b| b.build()).collect::<Result<Vec<_>, _>>()?;
Expand All @@ -235,7 +228,7 @@ impl WalletSubcommands {
println!("\nAccounts:");
for (i, wallet) in wallets.iter().enumerate() {
println!("- Account {i}:");
println!("Address: {}", wallet.address().to_alloy());
println!("Address: {}", wallet.address());
println!("Private key: 0x{}\n", hex::encode(wallet.signer().to_bytes()));
}
}
Expand Down Expand Up @@ -271,13 +264,12 @@ impl WalletSubcommands {
println!("0x{sig}");
}
WalletSubcommands::Verify { message, signature, address } => {
match signature.verify(Self::hex_str_to_bytes(&message)?, address.to_ethers()) {
Ok(_) => {
println!("Validation succeeded. Address {address} signed this message.")
}
Err(_) => {
println!("Validation failed. Address {address} did not sign this message.")
}
let recovered_address =
signature.recover_address_from_prehash(&B256::from_str(&message)?)?;
if recovered_address == address {
println!("Validation succeeded. Address {address} signed this message.");
} else {
println!("Validation failed. Address {address} did not sign this message.");
}
}
WalletSubcommands::Import { account_name, keystore_dir, raw_wallet_options } => {
Expand Down Expand Up @@ -371,10 +363,10 @@ flag to set your key via:
let index = if let Some(i) = mnemonic_index { i } else { 0 };
let wallet = builder
.clone()
.derivation_path(&format!("{derivation_path}{index}"))?
.derivation_path(format!("{derivation_path}{index}"))?
.build()?;
println!("- Account:");
println!("Address: {}", wallet.address().to_alloy());
println!("Address: {}", wallet.address());
println!("Private key: 0x{}\n", hex::encode(wallet.signer().to_bytes()));
}
};
Expand Down
12 changes: 5 additions & 7 deletions crates/cast/bin/cmd/wallet/vanity.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use alloy_primitives::Address;
use alloy_signer::{k256::ecdsa::SigningKey, utils::secret_key_to_address, LocalWallet, Signer};
use clap::{builder::TypedValueParser, Parser};
use ethers_core::{k256::ecdsa::SigningKey, rand, utils::secret_key_to_address};
use ethers_signers::{LocalWallet, Signer};
use eyre::Result;
use foundry_common::types::ToAlloy;
use rayon::iter::{self, ParallelIterator};
use regex::Regex;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -66,7 +64,7 @@ struct Wallets {
impl WalletData {
pub fn new(wallet: &LocalWallet) -> Self {
WalletData {
address: wallet.address().to_alloy().to_checksum(None),
address: wallet.address().to_checksum(None),
private_key: format!("0x{}", hex::encode(wallet.signer().to_bytes())),
}
}
Expand Down Expand Up @@ -156,11 +154,11 @@ impl VanityArgs {
timer.elapsed().as_secs(),
if nonce.is_some() { "\nContract address: " } else { "" },
if nonce.is_some() {
wallet.address().to_alloy().create(nonce.unwrap()).to_checksum(None)
wallet.address().create(nonce.unwrap()).to_checksum(None)
} else {
String::new()
},
wallet.address().to_alloy().to_checksum(None),
wallet.address().to_checksum(None),
hex::encode(wallet.signer().to_bytes()),
);

Expand Down Expand Up @@ -229,7 +227,7 @@ pub fn wallet_generator() -> iter::Map<iter::Repeat<()>, impl Fn(()) -> Generate
pub fn generate_wallet() -> GeneratedWallet {
let key = SigningKey::random(&mut rand::thread_rng());
let address = secret_key_to_address(&key);
(key, address.to_alloy())
(key, address)
}

/// A trait to match vanity addresses.
Expand Down
8 changes: 3 additions & 5 deletions crates/cast/src/base.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use alloy_primitives::{Sign, I256, U256};
use ethers_core::utils::ParseUnits;
use alloy_primitives::{utils::ParseUnits, Sign, I256, U256};
use eyre::Result;
use foundry_common::types::ToAlloy;
use std::{
convert::Infallible,
fmt::{Binary, Debug, Display, Formatter, LowerHex, Octal, Result as FmtResult, UpperHex},
Expand Down Expand Up @@ -281,8 +279,8 @@ impl From<I256> for NumberWithBase {
impl From<ParseUnits> for NumberWithBase {
fn from(value: ParseUnits) -> Self {
match value {
ParseUnits::U256(val) => val.to_alloy().into(),
ParseUnits::I256(val) => val.to_alloy().into(),
ParseUnits::U256(val) => val.into(),
ParseUnits::I256(val) => val.into(),
}
}
}
Expand Down
12 changes: 7 additions & 5 deletions crates/cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ use alloy_dyn_abi::{DynSolType, DynSolValue, FunctionExt};
use alloy_json_abi::ContractObject;
use alloy_primitives::{
utils::{keccak256, ParseUnits, Unit},
Address, I256, U256,
Address, Bytes, B256, I256, U256,
};
use alloy_rlp::Decodable;
use base::{Base, NumberWithBase, ToBase};
use chrono::NaiveDateTime;
use ethers_core::{
types::{transaction::eip2718::TypedTransaction, *},
types::{
transaction::eip2718::TypedTransaction, BlockId, BlockNumber, Filter, NameOrAddress,
Signature, H160, H256, U64,
},
utils::rlp,
};
use ethers_providers::{Middleware, PendingTransaction, PubsubClient};
Expand Down Expand Up @@ -264,7 +267,7 @@ where
None => raw_tx,
};
let tx = Bytes::from(hex::decode(raw_tx)?);
let res = self.provider.send_raw_transaction(tx).await?;
let res = self.provider.send_raw_transaction(tx.0.into()).await?;

Ok::<_, eyre::Error>(res)
}
Expand Down Expand Up @@ -1397,8 +1400,7 @@ impl SimpleCast {
}

let padded = format!("{s:0<64}");
// need to use the Debug implementation
Ok(format!("{:?}", H256::from_str(&padded)?))
Ok(padded.parse::<B256>()?.to_string())
}

/// Encodes string into bytes32 value
Expand Down
Loading