From e2617c9ab6ff39bf6db6e13b171fac491789bce6 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:43:55 -0800 Subject: [PATCH 01/11] cleanup db invocations --- crates/cli/src/main.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index e25fa11..04bcef6 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -16,6 +16,7 @@ static DB: LazyLock = std::sync::LazyLock::new(|| { async fn main() -> Result<(), Box> { let args = ContenderCli::parse_args(); let _ = DB.create_tables(); // ignore error; tables already exist + let db = DB.clone(); match args.command { ContenderSubcommand::Setup { @@ -23,7 +24,7 @@ async fn main() -> Result<(), Box> { rpc_url, private_keys, min_balance, - } => commands::setup(&DB.clone(), testfile, rpc_url, private_keys, min_balance).await?, + } => commands::setup(&db, testfile, rpc_url, private_keys, min_balance).await?, ContenderSubcommand::Spam { testfile, @@ -38,7 +39,7 @@ async fn main() -> Result<(), Box> { min_balance, } => { commands::spam( - &DB.clone(), + &db, SpamCommandArgs { testfile, rpc_url, @@ -55,9 +56,7 @@ async fn main() -> Result<(), Box> { .await? } - ContenderSubcommand::Report { id, out_file } => { - commands::report(&DB.clone(), id, out_file)? - } + ContenderSubcommand::Report { id, out_file } => commands::report(&db, id, out_file)?, ContenderSubcommand::Run { scenario, @@ -68,7 +67,7 @@ async fn main() -> Result<(), Box> { txs_per_duration, } => { commands::run( - &DB.clone(), + &db, scenario, rpc_url, private_key, From 39b26078eab094e83b830f1fcdfcdc3abc5f9e26 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:38:25 -0800 Subject: [PATCH 02/11] (WIP) support from_pool in setup steps; TODO: scale requests by #accts --- .../{types.rs => contender_subcommand.rs} | 17 +++++++ crates/cli/src/commands/mod.rs | 4 +- crates/cli/src/commands/setup.rs | 51 ++++++++++++++++--- crates/cli/src/commands/spam.rs | 4 +- crates/cli/src/main.rs | 20 +++++++- crates/cli/src/util.rs | 12 ++++- crates/core/src/test_scenario.rs | 1 + scenarios/univ2ConfigTest.toml | 20 +++++--- 8 files changed, 108 insertions(+), 21 deletions(-) rename crates/cli/src/commands/{types.rs => contender_subcommand.rs} (91%) diff --git a/crates/cli/src/commands/types.rs b/crates/cli/src/commands/contender_subcommand.rs similarity index 91% rename from crates/cli/src/commands/types.rs rename to crates/cli/src/commands/contender_subcommand.rs index 6dbd98b..b6e2aec 100644 --- a/crates/cli/src/commands/types.rs +++ b/crates/cli/src/commands/contender_subcommand.rs @@ -109,6 +109,23 @@ May be specified multiple times." default_value = "1.0" )] min_balance: String, + + /// The seed used to generate pool accounts. + #[arg( + short, + long, + long_help = "The seed used to generate pool accounts.", + default_value = "0xffffffffffffffffffffffffffffffff13131313131313131313131313131313" + )] + seed: String, + + /// The number of signers to generate for each pool. + #[arg( + short, + long = "signers-per-pool", + long_help = "The number of signers to generate for each pool." + )] + num_signers_per_pool: Option, }, #[command( diff --git a/crates/cli/src/commands/mod.rs b/crates/cli/src/commands/mod.rs index f41e287..d53de23 100644 --- a/crates/cli/src/commands/mod.rs +++ b/crates/cli/src/commands/mod.rs @@ -1,16 +1,16 @@ +mod contender_subcommand; mod report; mod run; mod setup; mod spam; -mod types; use clap::Parser; +pub use contender_subcommand::ContenderSubcommand; pub use report::report; pub use run::run; pub use setup::setup; pub use spam::{spam, SpamCommandArgs}; -pub use types::ContenderSubcommand; #[derive(Parser, Debug)] pub struct ContenderCli { diff --git a/crates/cli/src/commands/setup.rs b/crates/cli/src/commands/setup.rs index 05161e7..ebf1227 100644 --- a/crates/cli/src/commands/setup.rs +++ b/crates/cli/src/commands/setup.rs @@ -2,12 +2,17 @@ use alloy::{ network::AnyNetwork, primitives::utils::parse_ether, providers::ProviderBuilder, signers::local::PrivateKeySigner, transports::http::reqwest::Url, }; -use contender_core::{generator::RandSeed, test_scenario::TestScenario}; +use contender_core::{ + agent_controller::{AgentStore, SignerStore}, + generator::RandSeed, + test_scenario::TestScenario, +}; use contender_testfile::TestConfig; use std::str::FromStr; use crate::util::{ - check_private_keys_fns, find_insufficient_balance_addrs, get_signers_with_defaults, + check_private_keys_fns, find_insufficient_balance_addrs, fund_accounts, get_setup_pools, + get_signers_with_defaults, }; pub async fn setup( @@ -16,11 +21,14 @@ pub async fn setup( rpc_url: impl AsRef, private_keys: Option>, min_balance: String, + seed: RandSeed, + signers_per_period: usize, ) -> Result<(), Box> { let url = Url::parse(rpc_url.as_ref()).expect("Invalid RPC URL"); let rpc_client = ProviderBuilder::new() .network::() .on_http(url.to_owned()); + let eth_client = ProviderBuilder::new().on_http(url.to_owned()); let testconfig: TestConfig = TestConfig::from_file(testfile.as_ref())?; let min_balance = parse_ether(&min_balance)?; @@ -30,10 +38,10 @@ pub async fn setup( .iter() .map(|key| PrivateKeySigner::from_str(key).expect("invalid private key")) .collect::>(); - let signers = get_signers_with_defaults(private_keys); + let default_signers = get_signers_with_defaults(private_keys); check_private_keys_fns( &testconfig.setup.to_owned().unwrap_or_default(), - signers.as_slice(), + &default_signers, ); let broke_accounts = find_insufficient_balance_addrs( &user_signers.iter().map(|s| s.address()).collect::>(), @@ -42,17 +50,46 @@ pub async fn setup( ) .await?; if !broke_accounts.is_empty() { - panic!("Some accounts do not have sufficient balance"); + panic!("Insufficient balance in provided user account(s)"); + } + + let mut agents = AgentStore::new(); + let from_pools = get_setup_pools(&testconfig); + let mut all_signers = vec![]; + all_signers.extend_from_slice(&user_signers); + + for from_pool in &from_pools { + if agents.has_agent(from_pool) { + continue; + } + + let agent = SignerStore::new_random(signers_per_period, &seed, from_pool); + all_signers.extend_from_slice(&agent.signers); + agents.add_agent(from_pool, agent); } + println!("all signers: {:?}", all_signers); + println!("default_signers[0]: {:?}", default_signers[0]); + + fund_accounts( + &rpc_client, + ð_client, + min_balance, + &all_signers, + &default_signers[0], + ) + .await?; + + println!("****** funded accounts"); + let mut scenario = TestScenario::new( testconfig.to_owned(), db.clone().into(), url, None, RandSeed::new(), - &signers, - Default::default(), + &default_signers, + agents, ) .await?; diff --git a/crates/cli/src/commands/spam.rs b/crates/cli/src/commands/spam.rs index a982902..e21324a 100644 --- a/crates/cli/src/commands/spam.rs +++ b/crates/cli/src/commands/spam.rs @@ -14,7 +14,7 @@ use contender_core::{ use contender_testfile::TestConfig; use crate::util::{ - check_private_keys, fund_accounts, get_from_pools, get_signers_with_defaults, + check_private_keys, fund_accounts, get_signers_with_defaults, get_spam_pools, spam_callback_default, SpamCallbackType, }; @@ -57,7 +57,7 @@ pub async fn spam( .expect("No spam function calls found in testfile"); // distill all from_pool arguments from the spam requests - let from_pools = get_from_pools(&testconfig); + let from_pools = get_spam_pools(&testconfig); let mut agents = AgentStore::new(); let signers_per_period = args diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 04bcef6..de8d386 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -5,7 +5,7 @@ mod util; use std::sync::LazyLock; use commands::{ContenderCli, ContenderSubcommand, SpamCommandArgs}; -use contender_core::db::DbOps; +use contender_core::{db::DbOps, generator::RandSeed}; use contender_sqlite::SqliteDb; static DB: LazyLock = std::sync::LazyLock::new(|| { @@ -24,7 +24,23 @@ async fn main() -> Result<(), Box> { rpc_url, private_keys, min_balance, - } => commands::setup(&db, testfile, rpc_url, private_keys, min_balance).await?, + seed, + num_signers_per_pool, + } => { + if num_signers_per_pool.is_none() { + eprintln!("Warning: --signers-per-pool (-n) not specified; defaulting to 1"); + } + commands::setup( + &db, + testfile, + rpc_url, + private_keys, + min_balance, + RandSeed::seed_from_str(&seed), + num_signers_per_pool.unwrap_or(1), + ) + .await? + } ContenderSubcommand::Spam { testfile, diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index 5691b51..564e4c4 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -33,7 +33,17 @@ pub const DEFAULT_PRV_KEYS: [&str; 10] = [ "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", ]; -pub fn get_from_pools(testconfig: &TestConfig) -> Vec { +pub fn get_setup_pools(testconfig: &TestConfig) -> Vec { + testconfig + .setup + .to_owned() + .unwrap_or_default() + .into_iter() + .filter_map(|s| s.from_pool) + .collect() +} + +pub fn get_spam_pools(testconfig: &TestConfig) -> Vec { let mut from_pools = vec![]; let spam = testconfig .spam diff --git a/crates/core/src/test_scenario.rs b/crates/core/src/test_scenario.rs index 49c8810..99e0939 100644 --- a/crates/core/src/test_scenario.rs +++ b/crates/core/src/test_scenario.rs @@ -234,6 +234,7 @@ where let db = self.db.clone(); let rpc_url = self.rpc_url.clone(); let handle = tokio::task::spawn(async move { + println!("___running setup: {:?}", tx_req); let wallet = ProviderBuilder::new() .with_simple_nonce_management() .wallet(wallet) diff --git a/scenarios/univ2ConfigTest.toml b/scenarios/univ2ConfigTest.toml index 977d899..820c895 100644 --- a/scenarios/univ2ConfigTest.toml +++ b/scenarios/univ2ConfigTest.toml @@ -36,24 +36,26 @@ bytecode = "0x60c06040523480156200001157600080fd5b506040516200573e3803806200573e [[setup]] to = "{weth}" from = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +# from_pool = "pool1" signature = "function deposit() public payable" value = "10000000000000000000" [[setup]] to = "{weth}" -from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +from_pool = "pool1" signature = "function deposit() public payable" value = "10000000000000000000" [[setup]] to = "{weth}" -from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +from_pool = "pool2" signature = "function deposit() public payable" value = "10000000000000000000" ## uniV2 pair: weth/token ###################################################### - [[setup]] to = "{uniV2Factory}" from = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" @@ -87,7 +89,8 @@ args = [ # contender1 [[setup]] to = "{weth}" -from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +from_pool = "pool1" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ "{uniRouterV2}", @@ -96,7 +99,8 @@ args = [ [[setup]] to = "{testToken}" -from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +from_pool = "pool1" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ "{uniRouterV2}", @@ -106,7 +110,8 @@ args = [ # contender2 [[setup]] to = "{weth}" -from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +from_pool = "pool2" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ "{uniRouterV2}", @@ -115,7 +120,8 @@ args = [ [[setup]] to = "{testToken}" -from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +from_pool = "pool2" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ "{uniRouterV2}", From f3e9c1d45c1da3ee999359d945a717bccebac52a Mon Sep 17 00:00:00 2001 From: Brock Smedley <2791467+zeroXbrock@users.noreply.github.com> Date: Sat, 14 Dec 2024 12:41:14 -0800 Subject: [PATCH 03/11] use scaled from_pool accounts in setup generator --- crates/core/src/generator/mod.rs | 58 ++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/crates/core/src/generator/mod.rs b/crates/core/src/generator/mod.rs index b8a4eb1..e0d0200 100644 --- a/crates/core/src/generator/mod.rs +++ b/crates/core/src/generator/mod.rs @@ -203,27 +203,41 @@ where } PlanType::Setup(on_setup_step) => { let setup_steps = conf.get_setup_steps()?; - for step in setup_steps.iter() { - // lookup placeholders in DB & update map before templating - templater.find_fncall_placeholders(step, db, &mut placeholder_map)?; - - // setup tx with template values - let tx = NamedTxRequest::new( - templater.template_function_call( - &self.make_strict_call(step, 0)?, - &placeholder_map, - )?, - None, - step.kind.to_owned(), - ); - let handle = on_setup_step(tx.to_owned())?; - if let Some(handle) = handle { - handle.await.map_err(|e| { - ContenderError::with_err(e, "join error; callback crashed") - })?; + let agents = self.get_agent_store(); + let num_accts = agents + .all_agents() + .next() + .map(|(_, store)| store.signers.len()) + .unwrap_or(1); + + for i in 0..(num_accts) { + for step in setup_steps.iter() { + if i > 0 && step.from_pool.is_none() { + // only loop on from_pool steps; single-account steps can't be repeated + continue; + } + // lookup placeholders in DB & update map before templating + templater.find_fncall_placeholders(step, db, &mut placeholder_map)?; + + // setup tx with template values + let tx = NamedTxRequest::new( + templater.template_function_call( + &self.make_strict_call(step, i)?, // 'from' address injected here + &placeholder_map, + )?, + None, + step.kind.to_owned(), + ); + + let handle = on_setup_step(tx.to_owned())?; + if let Some(handle) = handle { + handle.await.map_err(|e| { + ContenderError::with_err(e, "join error; callback crashed") + })?; + } + txs.push(tx.into()); } - txs.push(tx.into()); } } PlanType::Spam(num_txs, on_spam_setup) => { @@ -281,7 +295,7 @@ where for step in spam_steps.iter() { // converts a FunctionCallDefinition to a NamedTxRequest (filling in fuzzable args), // returns a callback handle and the processed tx request - let process_tx = |req| { + let prepare_tx = |req| { let args = get_fuzzed_args(req, &canonical_fuzz_map, i); let fuzz_tx_value = get_fuzzed_tx_value(req, &canonical_fuzz_map, i); let mut req = req.to_owned(); @@ -304,7 +318,7 @@ where match step { SpamRequest::Tx(req) => { - let (handle, tx) = process_tx(req)?; + let (handle, tx) = prepare_tx(req)?; if let Some(handle) = handle { handle.await.map_err(|e| { ContenderError::with_err(e, "error from callback") @@ -315,7 +329,7 @@ where SpamRequest::Bundle(req) => { let mut bundle_txs = vec![]; for tx in req.txs.iter() { - let (handle, txr) = process_tx(tx)?; + let (handle, txr) = prepare_tx(tx)?; if let Some(handle) = handle { handle.await.map_err(|e| { ContenderError::with_err(e, "error from callback") From 8770685039e6b64a81b121ea68fa73351628c825 Mon Sep 17 00:00:00 2001 From: Brock Smedley <2791467+zeroXbrock@users.noreply.github.com> Date: Sat, 14 Dec 2024 14:13:28 -0800 Subject: [PATCH 04/11] use same default seed for both setup & spam --- crates/cli/src/commands/contender_subcommand.rs | 7 ++++--- crates/cli/src/commands/setup.rs | 2 +- crates/cli/src/commands/spam.rs | 7 ++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/crates/cli/src/commands/contender_subcommand.rs b/crates/cli/src/commands/contender_subcommand.rs index b6e2aec..ff94160 100644 --- a/crates/cli/src/commands/contender_subcommand.rs +++ b/crates/cli/src/commands/contender_subcommand.rs @@ -47,13 +47,14 @@ Requires --priv-key to be set for each 'from' address in the given testfile.", )] duration: Option, - /// The seed to use for generating spam transactions. If not provided, one is generated. + /// The seed to use for generating spam transactions & accounts. #[arg( short, long, - long_help = "The seed to use for generating spam transactions" + long_help = "The seed to use for generating spam transactions", + default_value = "0xffffffffffffffffffffffffffffffff13131313131313131313131313131313" )] - seed: Option, + seed: String, /// The private keys to use for blockwise spamming. /// Required if `txs_per_block` is set. diff --git a/crates/cli/src/commands/setup.rs b/crates/cli/src/commands/setup.rs index ebf1227..02ba032 100644 --- a/crates/cli/src/commands/setup.rs +++ b/crates/cli/src/commands/setup.rs @@ -87,7 +87,7 @@ pub async fn setup( db.clone().into(), url, None, - RandSeed::new(), + seed, &default_signers, agents, ) diff --git a/crates/cli/src/commands/spam.rs b/crates/cli/src/commands/spam.rs index e21324a..8387965 100644 --- a/crates/cli/src/commands/spam.rs +++ b/crates/cli/src/commands/spam.rs @@ -26,7 +26,7 @@ pub struct SpamCommandArgs { pub txs_per_block: Option, pub txs_per_second: Option, pub duration: Option, - pub seed: Option, + pub seed: String, pub private_keys: Option>, pub disable_reports: bool, pub min_balance: String, @@ -37,10 +37,7 @@ pub async fn spam( args: SpamCommandArgs, ) -> Result<(), Box> { let testconfig = TestConfig::from_file(&args.testfile)?; - let rand_seed = args - .seed - .map(|s| RandSeed::seed_from_str(s.as_ref())) - .unwrap_or_default(); + let rand_seed = RandSeed::seed_from_str(&args.seed); let url = Url::parse(&args.rpc_url).expect("Invalid RPC URL"); let rpc_client = ProviderBuilder::new() .network::() From 4188c4f4f4d11be9c0822040af33ab24bb88b4a4 Mon Sep 17 00:00:00 2001 From: Brock Smedley <2791467+zeroXbrock@users.noreply.github.com> Date: Sat, 14 Dec 2024 14:14:07 -0800 Subject: [PATCH 05/11] use from_pools in univ2 spam --- scenarios/univ2ConfigTest.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scenarios/univ2ConfigTest.toml b/scenarios/univ2ConfigTest.toml index 820c895..f3a67df 100644 --- a/scenarios/univ2ConfigTest.toml +++ b/scenarios/univ2ConfigTest.toml @@ -153,7 +153,8 @@ args = [ [spam.tx] kind = "uniswap_v2" to = "{uniRouterV2}" -from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +from_pool = "pool1" signature = "swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline) external returns (uint256[] memory)" args = [ "1000000000000000000", @@ -169,7 +170,8 @@ fuzz = [{param = "amountIn", min = "1", max = "100000000000000000"}] [spam.tx] kind = "uniswap_v2" to = "{uniRouterV2}" -from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +from_pool = "pool2" signature = "swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline) external returns (uint256[] memory)" args = [ "1000000000000000000", From 144caef2c11bd8118f9d3dc61ed3c9fba0e5f63c Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:54:52 -0800 Subject: [PATCH 06/11] clean up logs --- crates/cli/src/commands/setup.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/cli/src/commands/setup.rs b/crates/cli/src/commands/setup.rs index 02ba032..483260e 100644 --- a/crates/cli/src/commands/setup.rs +++ b/crates/cli/src/commands/setup.rs @@ -68,9 +68,6 @@ pub async fn setup( agents.add_agent(from_pool, agent); } - println!("all signers: {:?}", all_signers); - println!("default_signers[0]: {:?}", default_signers[0]); - fund_accounts( &rpc_client, ð_client, @@ -80,8 +77,6 @@ pub async fn setup( ) .await?; - println!("****** funded accounts"); - let mut scenario = TestScenario::new( testconfig.to_owned(), db.clone().into(), From 0576cd9584eda65cf807bce5f32e2509cefb7f1d Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:05:03 -0800 Subject: [PATCH 07/11] remove debug log --- crates/core/src/test_scenario.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/core/src/test_scenario.rs b/crates/core/src/test_scenario.rs index 99e0939..49c8810 100644 --- a/crates/core/src/test_scenario.rs +++ b/crates/core/src/test_scenario.rs @@ -234,7 +234,6 @@ where let db = self.db.clone(); let rpc_url = self.rpc_url.clone(); let handle = tokio::task::spawn(async move { - println!("___running setup: {:?}", tx_req); let wallet = ProviderBuilder::new() .with_simple_nonce_management() .wallet(wallet) From 3f8d3f84fab6d4fdb9bb19ff5f6f363ca6395af5 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:07:41 -0800 Subject: [PATCH 08/11] remove debug log --- crates/cli/src/main.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index de8d386..5ac088d 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -27,9 +27,6 @@ async fn main() -> Result<(), Box> { seed, num_signers_per_pool, } => { - if num_signers_per_pool.is_none() { - eprintln!("Warning: --signers-per-pool (-n) not specified; defaulting to 1"); - } commands::setup( &db, testfile, From b7a362fc7a8a09fd83ffcdad5384a144a7c8e82d Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:12:45 -0800 Subject: [PATCH 09/11] remove commented code --- scenarios/univ2ConfigTest.toml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scenarios/univ2ConfigTest.toml b/scenarios/univ2ConfigTest.toml index f3a67df..217a5b3 100644 --- a/scenarios/univ2ConfigTest.toml +++ b/scenarios/univ2ConfigTest.toml @@ -36,20 +36,17 @@ bytecode = "0x60c06040523480156200001157600080fd5b506040516200573e3803806200573e [[setup]] to = "{weth}" from = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" -# from_pool = "pool1" signature = "function deposit() public payable" value = "10000000000000000000" [[setup]] to = "{weth}" -# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" from_pool = "pool1" signature = "function deposit() public payable" value = "10000000000000000000" [[setup]] to = "{weth}" -# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" from_pool = "pool2" signature = "function deposit() public payable" value = "10000000000000000000" @@ -89,7 +86,6 @@ args = [ # contender1 [[setup]] to = "{weth}" -# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" from_pool = "pool1" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ @@ -99,7 +95,6 @@ args = [ [[setup]] to = "{testToken}" -# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" from_pool = "pool1" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ @@ -110,7 +105,6 @@ args = [ # contender2 [[setup]] to = "{weth}" -# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" from_pool = "pool2" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ @@ -120,7 +114,6 @@ args = [ [[setup]] to = "{testToken}" -# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" from_pool = "pool2" signature = "approve(address spender, uint256 amount) returns (bool)" args = [ @@ -153,7 +146,6 @@ args = [ [spam.tx] kind = "uniswap_v2" to = "{uniRouterV2}" -# from = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" from_pool = "pool1" signature = "swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline) external returns (uint256[] memory)" args = [ @@ -170,7 +162,6 @@ fuzz = [{param = "amountIn", min = "1", max = "100000000000000000"}] [spam.tx] kind = "uniswap_v2" to = "{uniRouterV2}" -# from = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" from_pool = "pool2" signature = "swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline) external returns (uint256[] memory)" args = [ From 7989febbebd7362f0b1b55116671c45aad0ccbda Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:57:15 -0800 Subject: [PATCH 10/11] add test for agent signers in setup step --- crates/core/src/test_scenario.rs | 87 ++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/crates/core/src/test_scenario.rs b/crates/core/src/test_scenario.rs index 49c8810..8ce2437 100644 --- a/crates/core/src/test_scenario.rs +++ b/crates/core/src/test_scenario.rs @@ -583,8 +583,9 @@ where #[cfg(test)] pub mod tests { - use crate::agent_controller::AgentStore; + use crate::agent_controller::{AgentStore, SignerStore}; use crate::db::MockDb; + use crate::generator::named_txs::ExecutionRequest; use crate::generator::templater::Templater; use crate::generator::types::{ CreateDefinition, FunctionCallDefinition, FuzzParam, SpamRequest, @@ -595,8 +596,11 @@ pub mod tests { use crate::test_scenario::TestScenario; use crate::Result; use alloy::hex::ToHexExt; + use alloy::network::{Ethereum, EthereumWallet, TransactionBuilder}; use alloy::node_bindings::AnvilInstance; - use alloy::primitives::Address; + use alloy::primitives::{Address, U256}; + use alloy::providers::{Provider, ProviderBuilder}; + use alloy::rpc::types::TransactionRequest; use std::collections::HashMap; pub struct MockConfig; @@ -654,6 +658,16 @@ pub mod tests { fuzz: None, kind: None, }, + FunctionCallDefinition { + to: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D".to_owned(), + from: None, + from_pool: Some("pool1".to_owned()), + value: None, + signature: "increment()".to_owned(), + args: vec![].into(), + fuzz: None, + kind: None, + }, ]) } @@ -723,6 +737,36 @@ pub mod tests { ) -> TestScenario { let seed = RandSeed::seed_from_bytes(&[0x01; 32]); let signers = &get_test_signers(); + let provider = ProviderBuilder::new() + .network::() + .on_http(anvil.endpoint_url()); + let mut agents = AgentStore::new(); + let pool1 = + SignerStore::new_random(10, &RandSeed::seed_from_str("0x0defa117"), "0x0defa117"); + let pool_signers = pool1.signers.to_vec(); + let admin = &signers[0]; + agents.add_agent("pool1", pool1); + let mut nonce = provider + .get_transaction_count(admin.address()) + .await + .unwrap(); + for signer in &pool_signers { + let tx = TransactionRequest::default() + .with_from(signers[0].address()) + .with_to(signer.address()) + .with_value(U256::from(100_000_000_000_000_000u128)) + .with_nonce(nonce) + .with_gas_price(10_000_000_000_u128) + .with_gas_limit(21000); + nonce += 1; + let signed_tx = tx + .build::(&admin.to_owned().into()) + .await + .unwrap(); + + let res = provider.send_tx_envelope(signed_tx).await.unwrap(); + res.get_receipt().await.unwrap(); + } TestScenario::new( MockConfig, @@ -731,7 +775,7 @@ pub mod tests { None, seed.to_owned(), signers, - AgentStore::new(), + agents, ) .await .unwrap() @@ -758,7 +802,7 @@ pub mod tests { })) .await .unwrap(); - assert_eq!(setup_txs.len(), 2); + assert_eq!(setup_txs.len(), 12); let spam_txs = scenario .load_txs(PlanType::Spam(20, |tx| { @@ -770,6 +814,41 @@ pub mod tests { assert!(spam_txs.len() >= 20); } + #[tokio::test] + async fn setup_steps_use_agent_signers() { + let anvil = spawn_anvil(); + let mut scenario = get_test_scenario(&anvil).await; + scenario.deploy_contracts().await.unwrap(); + let setup_steps = scenario + .load_txs(PlanType::Setup(|_| Ok(None))) + .await + .unwrap(); + scenario.run_setup().await.unwrap(); + let mut used_agent_keys = 0; + for step in setup_steps { + let tx = match step { + ExecutionRequest::Tx(tx) => tx, + _ => continue, + }; + let from = tx.tx.from.unwrap(); + assert!(scenario.wallet_map.contains_key(&from)); + assert!(scenario.agent_store.has_agent("pool1")); + if scenario + .agent_store + .get_agent("pool1") + .unwrap() + .signers + .iter() + .map(|s| s.address()) + .collect::>() + .contains(&from) + { + used_agent_keys += 1; + } + } + assert!(used_agent_keys > 1); + } + #[tokio::test] async fn scenario_creates_contracts() { let anvil = spawn_anvil(); From f1ecbe78498ed2867c096c6b82878d0659a7c393 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:03:38 -0800 Subject: [PATCH 11/11] use eip1559 txs to fund test scenario in tests --- crates/core/src/test_scenario.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/core/src/test_scenario.rs b/crates/core/src/test_scenario.rs index 8ce2437..fd32a36 100644 --- a/crates/core/src/test_scenario.rs +++ b/crates/core/src/test_scenario.rs @@ -750,14 +750,17 @@ pub mod tests { .get_transaction_count(admin.address()) .await .unwrap(); + let chain_id = anvil.chain_id(); for signer in &pool_signers { let tx = TransactionRequest::default() .with_from(signers[0].address()) .with_to(signer.address()) .with_value(U256::from(100_000_000_000_000_000u128)) .with_nonce(nonce) - .with_gas_price(10_000_000_000_u128) - .with_gas_limit(21000); + .with_max_fee_per_gas(10_000_000_000_u128) + .with_max_priority_fee_per_gas(1_000_000_000_u128) + .with_gas_limit(21000) + .with_chain_id(chain_id); nonce += 1; let signed_tx = tx .build::(&admin.to_owned().into())