From 439a5952d0ab35e0c147ca734c4aaa2cfdea5e15 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:32:20 -0800 Subject: [PATCH 1/4] check funder balance is sufficient to fund all accounts before funding any --- crates/cli/src/util.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index 17999d6..7df2751 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -166,6 +166,20 @@ pub async fn fund_accounts( let admin_nonce = rpc_client .get_transaction_count(fund_with.address()) .await?; + + // pre-check if admin account has sufficient balance + let gas_price = rpc_client.get_gas_price().await?; + let gas_cost_per_tx = U256::from(21000) * U256::from(gas_price + (gas_price / 10)); + + let total_cost = U256::from(insufficient_balance_addrs.len()) * (min_balance + gas_cost_per_tx); + if !is_balance_sufficient(&fund_with.address(), total_cost, rpc_client).await? { + return Err(format!( + "Admin account {} has insufficient balance to fund all accounts.", + fund_with.address() + ) + .into()); + } + for (idx, address) in insufficient_balance_addrs.iter().enumerate() { if !is_balance_sufficient(&fund_with.address(), min_balance, rpc_client).await? { // panic early if admin account runs out of funds @@ -178,7 +192,7 @@ pub async fn fund_accounts( let balance = rpc_client.get_balance(*address).await?; println!( - "Account {} has insufficient balance. (has {}, needed {})", + "Account {} has {}, needed {}", address, format_ether(balance), format_ether(min_balance) From 68cccb8eb20314a8a2207eced3d3f2fa9047bb27 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:00:16 -0800 Subject: [PATCH 2/4] fund accounts in blockwise spam test --- crates/core/src/test_scenario.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/core/src/test_scenario.rs b/crates/core/src/test_scenario.rs index af6cd4b..80a690a 100644 --- a/crates/core/src/test_scenario.rs +++ b/crates/core/src/test_scenario.rs @@ -615,9 +615,10 @@ pub mod tests { }; use crate::generator::{types::PlanType, util::test::spawn_anvil, RandSeed}; use crate::generator::{Generator, PlanConfig}; - use crate::spammer::util::test::get_test_signers; + use crate::spammer::util::test::{fund_account, get_test_signers}; use crate::test_scenario::TestScenario; use crate::Result; + use alloy::consensus::constants::ETH_TO_WEI; use alloy::hex::ToHexExt; use alloy::network::{Ethereum, EthereumWallet, TransactionBuilder}; use alloy::node_bindings::AnvilInstance; @@ -851,10 +852,29 @@ pub mod tests { agents.add_agent("pool2", pool2); agents.add_agent("admin1", admin1_signers); agents.add_agent("admin2", admin2_signers); + + // fund accounts let mut nonce = provider .get_transaction_count(admin.address()) .await .unwrap(); + for (_pool_name, agent) in agents.all_agents() { + for signer in &agent.signers { + let res = fund_account( + &signers[0], + signer.address(), + U256::from(ETH_TO_WEI), + &provider, + Some(nonce), + ) + .await + .unwrap(); + println!("funded signer: {:?}", res); + provider.watch_pending_transaction(res).await.unwrap(); + nonce += 1; + } + } + let chain_id = anvil.chain_id(); for signer in &pool_signers { let tx = TransactionRequest::default() From 081aa7c575e1e63a67a9e26809400eb5448f032b Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Wed, 15 Jan 2025 09:52:08 -0800 Subject: [PATCH 3/4] add test for fund_accounts: disallows funding early if sender has insufficient balance --- crates/cli/src/util.rs | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index 7df2751..3d5a3dd 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -304,3 +304,76 @@ pub fn prompt_cli(msg: impl AsRef) -> String { .expect("Failed to read line"); input.trim().to_owned() } + +#[cfg(test)] +mod test { + use std::str::FromStr; + + use alloy::{ + consensus::constants::ETH_TO_WEI, + network::AnyNetwork, + node_bindings::{Anvil, AnvilInstance}, + primitives::{Address, U256}, + providers::{Provider, ProviderBuilder}, + signers::local::PrivateKeySigner, + }; + + use super::fund_accounts; + + pub fn spawn_anvil() -> AnvilInstance { + Anvil::new().block_time(1).spawn() + } + + #[tokio::test] + async fn fund_accounts_disallows_insufficient_balance() { + let anvil = spawn_anvil(); + let rpc_client = ProviderBuilder::new() + .network::() + .on_http(anvil.endpoint_url()); + let eth_client = ProviderBuilder::new().on_http(anvil.endpoint_url()); + let min_balance = U256::from(ETH_TO_WEI); + let default_signer = PrivateKeySigner::from_str(super::DEFAULT_PRV_KEYS[0]).unwrap(); + // address: 0x7E57f00F16dE6A0D6B720E9C0af5C869a1f71c66 + let new_signer = PrivateKeySigner::from_str( + "0x08a418b870bf01990abc730a1cfc4ff04811f8e88bafa9edb8d40d802a33891f", + ) + .unwrap(); + let recipient_addresses: Vec
= [ + "0x0000000000000000000000000000000000000013", + "0x7E57f00F16dE6A0D6B720E9C0af5C869a1f71c66", + ] + .iter() + .map(|s| s.parse().unwrap()) + .collect(); + + // send eth to the new signer + fund_accounts( + &recipient_addresses, + &default_signer, + &rpc_client, + ð_client, + min_balance, + ) + .await + .unwrap(); + + for addr in &recipient_addresses { + let balance = rpc_client.get_balance(*addr).await.unwrap(); + println!("balance of {}: {}", addr, balance); + assert_eq!(balance, U256::from(ETH_TO_WEI)); + } + + let res = fund_accounts( + &vec!["0x0000000000000000000000000000000000000014" + .parse::
() + .unwrap()], + &new_signer, + &rpc_client, + ð_client, + min_balance, + ) + .await; + println!("res: {:?}", res); + assert!(res.is_err()); + } +} From 75573ce9222ab3ab4f835e632d31f3646f927a82 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Wed, 15 Jan 2025 10:22:35 -0800 Subject: [PATCH 4/4] remove unnecessary vec --- crates/cli/src/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index 3d5a3dd..e640955 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -364,7 +364,7 @@ mod test { } let res = fund_accounts( - &vec!["0x0000000000000000000000000000000000000014" + &["0x0000000000000000000000000000000000000014" .parse::
() .unwrap()], &new_signer,