From 56e069c524c1c94b1e7a84a00a39fd2e36c4c9bd Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 12 May 2026 13:08:00 -0400 Subject: [PATCH 1/3] add scenario access list support --- crates/core/src/generator/function_def.rs | 43 ++++++ crates/core/src/generator/templater.rs | 177 +++++++++++++++++++++- crates/core/src/generator/trait.rs | 1 + crates/testfile/src/lib.rs | 36 +++++ docs/creating_scenarios.md | 24 +++ 5 files changed, 278 insertions(+), 3 deletions(-) diff --git a/crates/core/src/generator/function_def.rs b/crates/core/src/generator/function_def.rs index 3cc307cd..3b3dd8ac 100644 --- a/crates/core/src/generator/function_def.rs +++ b/crates/core/src/generator/function_def.rs @@ -42,12 +42,24 @@ pub struct FunctionCallDefinition { /// Optional setCode data; tx type must be set to EIP7702 by spammer #[serde(skip_serializing_if = "Option::is_none")] pub authorization_address: Option, + /// Optional EIP-2930 access list entries to include in the transaction. + #[serde(skip_serializing_if = "Option::is_none")] + pub access_list: Option>, /// If true and `from_pool` is set, run this setup transaction for all accounts in the pool. /// Defaults to false (only runs for the first account). #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub for_all_accounts: bool, } +/// User-facing EIP-2930 access list entry. +#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Serialize)] +pub struct AccessListDefinition { + /// Account address to warm before execution. + pub address: String, + /// Storage keys to warm for `address`. + pub storage_keys: Vec, +} + /// User-facing definition of a function call to be executed. #[derive(Clone, Deserialize, Debug, Serialize)] pub struct BundleCallDefinition { @@ -69,6 +81,7 @@ impl FunctionCallDefinition { gas_limit: None, blob_data: None, authorization_address: None, + access_list: None, for_all_accounts: false, } } @@ -118,6 +131,10 @@ impl FunctionCallDefinition { self.authorization_address = Some(auth_addr.as_ref().to_owned()); self } + pub fn with_access_list(mut self, access_list: Vec) -> Self { + self.access_list = Some(access_list); + self + } pub fn with_for_all_accounts(mut self, for_all_accounts: bool) -> Self { self.for_all_accounts = for_all_accounts; self @@ -156,6 +173,7 @@ pub struct FunctionCallDefinitionStrict { pub gas_limit: Option, pub sidecar: Option, pub authorization: Option>, + pub access_list: Option>, } #[derive(Clone, Deserialize, Debug, Serialize)] @@ -221,4 +239,29 @@ mod tests { .with_for_all_accounts(false); assert!(!def.for_all_accounts); } + + #[test] + fn access_list_parses_from_toml() { + let toml = r#" + to = "0x1234567890123456789012345678901234567890" + from_pool = "test_pool" + signature = "test()" + + [[access_list]] + address = "0x4200000000000000000000000000000000000022" + storage_keys = [ + "0x0100000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000", + ] + "#; + let def: FunctionCallDefinition = toml::from_str(toml).unwrap(); + let access_list = def.access_list.unwrap(); + + assert_eq!(access_list.len(), 1); + assert_eq!( + access_list[0].address, + "0x4200000000000000000000000000000000000022" + ); + assert_eq!(access_list[0].storage_keys.len(), 2); + } } diff --git a/crates/core/src/generator/templater.rs b/crates/core/src/generator/templater.rs index 8c58b80e..df5e5cdb 100644 --- a/crates/core/src/generator/templater.rs +++ b/crates/core/src/generator/templater.rs @@ -2,14 +2,17 @@ use crate::{ db::{DbError, DbOps}, generator::{ constants::{SENDER_KEY, SETCODE_KEY}, - function_def::{FunctionCallDefinition, FunctionCallDefinitionStrict}, + function_def::{ + AccessListDefinition, FunctionCallDefinition, FunctionCallDefinitionStrict, + }, util::{encode_calldata, scenario_db_key, UtilError}, CreateDefinition, }, }; use alloy::{ + eips::eip2930::{AccessList, AccessListItem}, hex::{FromHex, ToHexExt}, - primitives::{Address, Bytes, FixedBytes, TxKind, U256}, + primitives::{Address, Bytes, FixedBytes, TxKind, B256, U256}, rpc::types::TransactionRequest, }; use std::collections::HashMap; @@ -33,6 +36,9 @@ pub enum TemplaterError { #[error("failed to parse address '{0}'")] ParseAddressFailed(String), + #[error("failed to parse storage key '{0}'")] + ParseStorageKeyFailed(String), + #[error("templater util error")] Util(#[from] UtilError), } @@ -105,7 +111,7 @@ where /// Finds {placeholders} in `fncall` and looks them up in `db`, /// then inserts the values it finds into `placeholder_map`. - /// NOTE: only finds placeholders in `args`, `authorization_addr`, and `to` fields. + /// NOTE: only finds placeholders in `args`, `authorization_addr`, `access_list`, and `to` fields. fn find_fncall_placeholders( &self, fncall: &FunctionCallDefinition, @@ -155,9 +161,63 @@ where scenario_label, )?; } + if let Some(access_list) = &fncall.access_list { + for entry in access_list { + self.find_placeholder_values( + &entry.address, + placeholder_map, + db, + rpc_url, + genesis_hash, + scenario_label, + )?; + for storage_key in &entry.storage_keys { + self.find_placeholder_values( + storage_key, + placeholder_map, + db, + rpc_url, + genesis_hash, + scenario_label, + )?; + } + } + } Ok(()) } + fn template_access_list( + &self, + access_list: &[AccessListDefinition], + placeholder_map: &HashMap, + ) -> Result { + access_list + .iter() + .map(|entry| { + let address = self.replace_placeholders(&entry.address, placeholder_map); + let address = address + .parse::
() + .map_err(|_| TemplaterError::ParseAddressFailed(address))?; + let storage_keys = entry + .storage_keys + .iter() + .map(|storage_key| { + let storage_key = self.replace_placeholders(storage_key, placeholder_map); + storage_key + .parse::() + .map_err(|_| TemplaterError::ParseStorageKeyFailed(storage_key)) + }) + .collect::>>()?; + + Ok(AccessListItem { + address, + storage_keys, + }) + }) + .collect::>>() + .map(AccessList::from) + } + /// Finds {placeholders} in create constructor args and updates the placeholder map. fn find_create_placeholders( &self, @@ -225,6 +285,11 @@ where .as_ref() .map(|x| self.replace_placeholders(x, placeholder_map)) .and_then(|s| s.parse::().ok()); + let access_list = funcdef + .access_list + .as_deref() + .map(|list| self.template_access_list(list, placeholder_map)) + .transpose()?; Ok(TransactionRequest { to: Some(TxKind::Call(to)), @@ -234,6 +299,7 @@ where gas: funcdef.gas_limit, sidecar: funcdef.sidecar.as_ref().map(|sc| sc.to_owned().into()), authorization_list: funcdef.authorization.to_owned(), + access_list, ..Default::default() }) } @@ -285,3 +351,108 @@ where Ok(tx) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::generator::{ + function_def::{AccessListDefinition, FunctionCallDefinitionStrict}, + util::complete_tx_request, + }; + use alloy::consensus::TxType; + use std::collections::HashMap; + + struct TestTemplater; + + impl Templater for TestTemplater { + fn replace_placeholders( + &self, + input: &str, + placeholder_map: &HashMap, + ) -> String { + let mut output = input.to_owned(); + for (key, value) in placeholder_map { + output = output.replace(&format!("{{{key}}}"), value); + } + output + } + + fn terminator_start(&self, input: &str) -> Option { + input.find('{') + } + + fn terminator_end(&self, input: &str) -> Option { + input.find('}') + } + + fn copy_end(&self, input: &str, last_end: usize) -> String { + input[last_end..].to_string() + } + + fn num_placeholders(&self, input: &str) -> usize { + input.matches('{').count() + } + + fn find_key(&self, input: &str) -> Option<(String, usize)> { + let start = self.terminator_start(input)?; + let end = self.terminator_end(input)?; + Some((input[start + 1..end].to_string(), end)) + } + } + + #[test] + fn template_function_call_threads_access_list_into_request() { + let templater = TestTemplater; + let access_list_address = "0x4200000000000000000000000000000000000022"; + let storage_key = "0x0100000000000000000000000000000000000000000000000000000000000000"; + let placeholder_storage_key = + "0x0300000000000000000000000000000000000000000000000000000000000000"; + let placeholder_map = HashMap::from([( + "lookup_key".to_string(), + placeholder_storage_key.to_string(), + )]); + let funcdef = FunctionCallDefinitionStrict { + to: access_list_address.to_string(), + from: Address::ZERO, + signature: "validate()".to_string(), + args: vec![], + value: None, + fuzz: vec![], + kind: None, + gas_limit: Some(200_000), + sidecar: None, + authorization: None, + access_list: Some(vec![AccessListDefinition { + address: access_list_address.to_string(), + storage_keys: vec![storage_key.to_string(), "{lookup_key}".to_string()], + }]), + }; + + let mut tx = templater + .template_function_call(&funcdef, &placeholder_map) + .unwrap(); + let access_list = tx.access_list.as_ref().unwrap(); + + assert_eq!(access_list.len(), 1); + assert_eq!( + access_list[0].address, + access_list_address.parse::
().unwrap() + ); + assert_eq!(access_list[0].storage_keys.len(), 2); + assert_eq!( + access_list[0].storage_keys[0], + storage_key.parse::().unwrap() + ); + assert_eq!( + access_list[0].storage_keys[1], + placeholder_storage_key.parse::().unwrap() + ); + + complete_tx_request(&mut tx, TxType::Eip1559, 10, 1, 200_000, 1, 0); + + assert_eq!(tx.access_list.unwrap().len(), 1); + assert_eq!(tx.max_fee_per_gas, Some(10)); + assert_eq!(tx.max_priority_fee_per_gas, Some(1)); + assert_eq!(tx.chain_id, Some(1)); + } +} diff --git a/crates/core/src/generator/trait.rs b/crates/core/src/generator/trait.rs index 0992ae95..2dfeda93 100644 --- a/crates/core/src/generator/trait.rs +++ b/crates/core/src/generator/trait.rs @@ -327,6 +327,7 @@ where gas_limit: funcdef.gas_limit.to_owned(), sidecar: funcdef.sidecar_data()?, authorization: signed_auth.map(|a| vec![a]), + access_list: funcdef.access_list.to_owned(), }) } diff --git a/crates/testfile/src/lib.rs b/crates/testfile/src/lib.rs index 197c7a8a..5b98e7e2 100644 --- a/crates/testfile/src/lib.rs +++ b/crates/testfile/src/lib.rs @@ -214,6 +214,42 @@ pub mod tests { } } + #[test] + fn parses_spam_tx_access_list_toml() { + let test_file = TestConfig::from_str( + r#" + [[spam]] + [spam.tx] + to = "0x4200000000000000000000000000000000000022" + from_pool = "spammers" + signature = "validate()" + gas_limit = 200000 + + [[spam.tx.access_list]] + address = "0x4200000000000000000000000000000000000022" + storage_keys = [ + "0x0100000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000", + ] + "#, + ) + .unwrap(); + let spam = test_file.spam.unwrap(); + + match &spam[0] { + SpamRequest::Tx(fncall) => { + let access_list = fncall.access_list.as_ref().unwrap(); + assert_eq!(access_list.len(), 1); + assert_eq!( + access_list[0].address, + "0x4200000000000000000000000000000000000022" + ); + assert_eq!(access_list[0].storage_keys.len(), 2); + } + SpamRequest::Bundle(_) => panic!("expected SpamRequest::Tx"), + } + } + fn repo_root_path() -> std::path::PathBuf { let mut dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); dir.pop(); // crates diff --git a/docs/creating_scenarios.md b/docs/creating_scenarios.md index 6721d11b..b742f817 100644 --- a/docs/creating_scenarios.md +++ b/docs/creating_scenarios.md @@ -207,6 +207,30 @@ args = ["1350000"] gas_limit = 1350000 ``` +### access lists + +Spam transactions can include EIP-2930 access-list entries. This is useful for workloads that already know which account and storage keys need to be warm, while still sending EIP-1559 transactions by default. + +```toml +[[spam]] + +[spam.tx] +to = "0x1111111111111111111111111111111111111111" +from_pool = "bluepool" +signature = "touch(bytes32 lookupKey)" +args = [ + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +] +gas_limit = 200000 + +[[spam.tx.access_list]] +address = "0x1111111111111111111111111111111111111111" +storage_keys = [ + "0x0100000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000", +] +``` + ### sending bundles The `[spam.tx]` directive sends a mempool transaction using `eth_sendRawTransaction`, but Contender also supports bundles. From 53413065d3536fa4b92e0c5c41cff70e2be7b9c3 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 12 May 2026 18:28:27 -0400 Subject: [PATCH 2/3] use alloy access list items --- crates/core/src/generator/function_def.rs | 20 ++--- crates/core/src/generator/templater.rs | 99 ++++------------------- crates/testfile/src/lib.rs | 4 +- docs/creating_scenarios.md | 2 +- 4 files changed, 26 insertions(+), 99 deletions(-) diff --git a/crates/core/src/generator/function_def.rs b/crates/core/src/generator/function_def.rs index 3b3dd8ac..4ff520f8 100644 --- a/crates/core/src/generator/function_def.rs +++ b/crates/core/src/generator/function_def.rs @@ -4,6 +4,7 @@ use alloy::{ eips::eip7702::SignedAuthorization, hex::{FromHex, ToHexExt}, primitives::{Address, Bytes, U256}, + rpc::types::AccessListItem, }; use serde::{Deserialize, Serialize}; @@ -44,22 +45,13 @@ pub struct FunctionCallDefinition { pub authorization_address: Option, /// Optional EIP-2930 access list entries to include in the transaction. #[serde(skip_serializing_if = "Option::is_none")] - pub access_list: Option>, + pub access_list: Option>, /// If true and `from_pool` is set, run this setup transaction for all accounts in the pool. /// Defaults to false (only runs for the first account). #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub for_all_accounts: bool, } -/// User-facing EIP-2930 access list entry. -#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Serialize)] -pub struct AccessListDefinition { - /// Account address to warm before execution. - pub address: String, - /// Storage keys to warm for `address`. - pub storage_keys: Vec, -} - /// User-facing definition of a function call to be executed. #[derive(Clone, Deserialize, Debug, Serialize)] pub struct BundleCallDefinition { @@ -131,7 +123,7 @@ impl FunctionCallDefinition { self.authorization_address = Some(auth_addr.as_ref().to_owned()); self } - pub fn with_access_list(mut self, access_list: Vec) -> Self { + pub fn with_access_list(mut self, access_list: Vec) -> Self { self.access_list = Some(access_list); self } @@ -173,7 +165,7 @@ pub struct FunctionCallDefinitionStrict { pub gas_limit: Option, pub sidecar: Option, pub authorization: Option>, - pub access_list: Option>, + pub access_list: Option>, } #[derive(Clone, Deserialize, Debug, Serialize)] @@ -249,7 +241,7 @@ mod tests { [[access_list]] address = "0x4200000000000000000000000000000000000022" - storage_keys = [ + storageKeys = [ "0x0100000000000000000000000000000000000000000000000000000000000000", "0x0300000000000000000000000000000000000000000000000000000000000000", ] @@ -259,7 +251,7 @@ mod tests { assert_eq!(access_list.len(), 1); assert_eq!( - access_list[0].address, + access_list[0].address.to_string(), "0x4200000000000000000000000000000000000022" ); assert_eq!(access_list[0].storage_keys.len(), 2); diff --git a/crates/core/src/generator/templater.rs b/crates/core/src/generator/templater.rs index df5e5cdb..b1d52f97 100644 --- a/crates/core/src/generator/templater.rs +++ b/crates/core/src/generator/templater.rs @@ -2,18 +2,15 @@ use crate::{ db::{DbError, DbOps}, generator::{ constants::{SENDER_KEY, SETCODE_KEY}, - function_def::{ - AccessListDefinition, FunctionCallDefinition, FunctionCallDefinitionStrict, - }, + function_def::{FunctionCallDefinition, FunctionCallDefinitionStrict}, util::{encode_calldata, scenario_db_key, UtilError}, CreateDefinition, }, }; use alloy::{ - eips::eip2930::{AccessList, AccessListItem}, hex::{FromHex, ToHexExt}, - primitives::{Address, Bytes, FixedBytes, TxKind, B256, U256}, - rpc::types::TransactionRequest, + primitives::{Address, Bytes, FixedBytes, TxKind, U256}, + rpc::types::{AccessList, TransactionRequest}, }; use std::collections::HashMap; use thiserror::Error; @@ -36,9 +33,6 @@ pub enum TemplaterError { #[error("failed to parse address '{0}'")] ParseAddressFailed(String), - #[error("failed to parse storage key '{0}'")] - ParseStorageKeyFailed(String), - #[error("templater util error")] Util(#[from] UtilError), } @@ -111,7 +105,7 @@ where /// Finds {placeholders} in `fncall` and looks them up in `db`, /// then inserts the values it finds into `placeholder_map`. - /// NOTE: only finds placeholders in `args`, `authorization_addr`, `access_list`, and `to` fields. + /// NOTE: only finds placeholders in `args`, `authorization_addr`, and `to` fields. fn find_fncall_placeholders( &self, fncall: &FunctionCallDefinition, @@ -161,63 +155,9 @@ where scenario_label, )?; } - if let Some(access_list) = &fncall.access_list { - for entry in access_list { - self.find_placeholder_values( - &entry.address, - placeholder_map, - db, - rpc_url, - genesis_hash, - scenario_label, - )?; - for storage_key in &entry.storage_keys { - self.find_placeholder_values( - storage_key, - placeholder_map, - db, - rpc_url, - genesis_hash, - scenario_label, - )?; - } - } - } Ok(()) } - fn template_access_list( - &self, - access_list: &[AccessListDefinition], - placeholder_map: &HashMap, - ) -> Result { - access_list - .iter() - .map(|entry| { - let address = self.replace_placeholders(&entry.address, placeholder_map); - let address = address - .parse::
() - .map_err(|_| TemplaterError::ParseAddressFailed(address))?; - let storage_keys = entry - .storage_keys - .iter() - .map(|storage_key| { - let storage_key = self.replace_placeholders(storage_key, placeholder_map); - storage_key - .parse::() - .map_err(|_| TemplaterError::ParseStorageKeyFailed(storage_key)) - }) - .collect::>>()?; - - Ok(AccessListItem { - address, - storage_keys, - }) - }) - .collect::>>() - .map(AccessList::from) - } - /// Finds {placeholders} in create constructor args and updates the placeholder map. fn find_create_placeholders( &self, @@ -285,11 +225,7 @@ where .as_ref() .map(|x| self.replace_placeholders(x, placeholder_map)) .and_then(|s| s.parse::().ok()); - let access_list = funcdef - .access_list - .as_deref() - .map(|list| self.template_access_list(list, placeholder_map)) - .transpose()?; + let access_list = funcdef.access_list.to_owned().map(AccessList::from); Ok(TransactionRequest { to: Some(TxKind::Call(to)), @@ -355,11 +291,10 @@ where #[cfg(test)] mod tests { use super::*; - use crate::generator::{ - function_def::{AccessListDefinition, FunctionCallDefinitionStrict}, - util::complete_tx_request, - }; + use crate::generator::{function_def::FunctionCallDefinitionStrict, util::complete_tx_request}; use alloy::consensus::TxType; + use alloy::primitives::B256; + use alloy::rpc::types::AccessListItem; use std::collections::HashMap; struct TestTemplater; @@ -405,12 +340,9 @@ mod tests { let templater = TestTemplater; let access_list_address = "0x4200000000000000000000000000000000000022"; let storage_key = "0x0100000000000000000000000000000000000000000000000000000000000000"; - let placeholder_storage_key = + let second_storage_key = "0x0300000000000000000000000000000000000000000000000000000000000000"; - let placeholder_map = HashMap::from([( - "lookup_key".to_string(), - placeholder_storage_key.to_string(), - )]); + let placeholder_map = HashMap::new(); let funcdef = FunctionCallDefinitionStrict { to: access_list_address.to_string(), from: Address::ZERO, @@ -422,9 +354,12 @@ mod tests { gas_limit: Some(200_000), sidecar: None, authorization: None, - access_list: Some(vec![AccessListDefinition { - address: access_list_address.to_string(), - storage_keys: vec![storage_key.to_string(), "{lookup_key}".to_string()], + access_list: Some(vec![AccessListItem { + address: access_list_address.parse::
().unwrap(), + storage_keys: vec![ + storage_key.parse::().unwrap(), + second_storage_key.parse::().unwrap(), + ], }]), }; @@ -445,7 +380,7 @@ mod tests { ); assert_eq!( access_list[0].storage_keys[1], - placeholder_storage_key.parse::().unwrap() + second_storage_key.parse::().unwrap() ); complete_tx_request(&mut tx, TxType::Eip1559, 10, 1, 200_000, 1, 0); diff --git a/crates/testfile/src/lib.rs b/crates/testfile/src/lib.rs index 5b98e7e2..d1241de6 100644 --- a/crates/testfile/src/lib.rs +++ b/crates/testfile/src/lib.rs @@ -227,7 +227,7 @@ pub mod tests { [[spam.tx.access_list]] address = "0x4200000000000000000000000000000000000022" - storage_keys = [ + storageKeys = [ "0x0100000000000000000000000000000000000000000000000000000000000000", "0x0300000000000000000000000000000000000000000000000000000000000000", ] @@ -241,7 +241,7 @@ pub mod tests { let access_list = fncall.access_list.as_ref().unwrap(); assert_eq!(access_list.len(), 1); assert_eq!( - access_list[0].address, + access_list[0].address.to_string(), "0x4200000000000000000000000000000000000022" ); assert_eq!(access_list[0].storage_keys.len(), 2); diff --git a/docs/creating_scenarios.md b/docs/creating_scenarios.md index b742f817..d2b98aa1 100644 --- a/docs/creating_scenarios.md +++ b/docs/creating_scenarios.md @@ -225,7 +225,7 @@ gas_limit = 200000 [[spam.tx.access_list]] address = "0x1111111111111111111111111111111111111111" -storage_keys = [ +storageKeys = [ "0x0100000000000000000000000000000000000000000000000000000000000000", "0x0300000000000000000000000000000000000000000000000000000000000000", ] From 72d280847f479f44ad4ada1066343a7b0c9c1d77 Mon Sep 17 00:00:00 2001 From: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com> Date: Tue, 12 May 2026 15:47:49 -0700 Subject: [PATCH 3/3] chore: update openrpc.json via cargo build --- crates/cli/src/server/static/openrpc.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/server/static/openrpc.json b/crates/cli/src/server/static/openrpc.json index cbb7ef58..7804377a 100644 --- a/crates/cli/src/server/static/openrpc.json +++ b/crates/cli/src/server/static/openrpc.json @@ -15,7 +15,7 @@ "BlobsCliArgs": {"file":"crates/cli/src/default_scenarios/blobs.rs","line":10}, "BuilderParams": {"file":"crates/cli/src/server/rpc_server/types.rs","line":227}, "BuiltinScenarioCli": {"file":"crates/cli/src/default_scenarios/builtin.rs","line":33}, - "BundleCallDefinition": {"file":"crates/core/src/generator/function_def.rs","line":53}, + "BundleCallDefinition": {"file":"crates/core/src/generator/function_def.rs","line":57}, "BundleTypeCli": {"file":"crates/cli/src/commands/common.rs","line":438}, "CompiledContract": {"file":"crates/core/src/generator/create_def.rs","line":8}, "ContenderSessionInfo": {"file":"crates/cli/src/server/sessions.rs","line":128}, @@ -27,9 +27,9 @@ "EthereumOpcode": {"file":"crates/cli/src/default_scenarios/eth_functions/opcodes.rs","line":10}, "EthereumPrecompile": {"file":"crates/cli/src/default_scenarios/eth_functions/precompiles.rs","line":11}, "FillBlockCliArgs": {"file":"crates/cli/src/default_scenarios/fill_block.rs","line":17}, - "FunctionCallDefinition": {"file":"crates/core/src/generator/function_def.rs","line":12}, + "FunctionCallDefinition": {"file":"crates/core/src/generator/function_def.rs","line":13}, "FundAccountsParams": {"file":"crates/cli/src/server/rpc_server/types.rs","line":273}, - "FuzzParam": {"file":"crates/core/src/generator/function_def.rs","line":162}, + "FuzzParam": {"file":"crates/core/src/generator/function_def.rs","line":172}, "RevertCliArgs": {"file":"crates/cli/src/default_scenarios/revert.rs","line":8}, "ServerStatus": {"file":"crates/cli/src/server/rpc_server/types.rs","line":33}, "SessionOptions": {"file":"crates/cli/src/server/rpc_server/types.rs","line":234}, @@ -188,7 +188,7 @@ "EthereumOpcode": {"type":"string","enum":["Stop","Add","Mul","Sub","Div","Sdiv","Mod","Smod","Addmod","Mulmod","Exp","Signextend","Lt","Gt","Slt","Sgt","Eq","Iszero","And","Or","Xor","Not","Byte","Shl","Shr","Sar","Sha3","Keccak256","Address","Balance","Origin","Caller","Callvalue","Calldataload","Calldatasize","Calldatacopy","Codesize","Codecopy","Gasprice","Extcodesize","Extcodecopy","Returndatasize","Returndatacopy","Extcodehash","Blockhash","Coinbase","Timestamp","Number","Prevrandao","Gaslimit","Chainid","Selfbalance","Basefee","Pop","Mload","Mstore","Mstore8","Sload","Sstore","Msize","Gas","Log0","Log1","Log2","Log3","Log4","Create","Call","Callcode","Return","Delegatecall","Create2","Staticcall","Revert","Invalid","Selfdestruct"]}, "EthereumPrecompile": {"type":"string","enum":["HashSha256","HashRipemd160","Identity","ModExp","EcAdd","EcMul","EcPairing","Blake2f"]}, "FillBlockCliArgs": {"description":"Taken from the CLI, this is used to fill a block with transactions.","type":"object","properties":{"max_gas_per_block":{"type":"integer"}}}, - "FunctionCallDefinition": {"description":"User-facing definition of a function call to be executed.","type":"object","properties":{"to":{"description":"Address of the contract to call.","type":"string"},"from":{"description":"Address of the tx sender.","type":"string"},"from_pool":{"description":"Get a `from` address from the pool of signers specified here.","type":"string"},"signature":{"description":"Name of the function to call.","type":"string"},"args":{"description":"Parameters to pass to the function.","type":"array","items":{"type":"string"}},"value":{"description":"Value in wei to send with the tx.","type":"string"},"fuzz":{"description":"Parameters to fuzz during the test.","type":"array","items":{"$ref":"#/components/schemas/FuzzParam"}},"kind":{"description":"Optional type of the spam transaction for categorization.","type":"string"},"gas_limit":{"description":"Optional gas limit, which will skip gas estimation. This allows reverting txs to be sent.","type":"integer"},"blob_data":{"description":"Optional blob data; tx type must be set to EIP4844 by spammer","type":"string"},"authorization_address":{"description":"Optional setCode data; tx type must be set to EIP7702 by spammer","type":"string"},"for_all_accounts":{"description":"If true and `from_pool` is set, run this setup transaction for all accounts in the pool. Defaults to false (only runs for the first account).","type":"boolean"}},"required":["to","for_all_accounts"]}, + "FunctionCallDefinition": {"description":"User-facing definition of a function call to be executed.","type":"object","properties":{"to":{"description":"Address of the contract to call.","type":"string"},"from":{"description":"Address of the tx sender.","type":"string"},"from_pool":{"description":"Get a `from` address from the pool of signers specified here.","type":"string"},"signature":{"description":"Name of the function to call.","type":"string"},"args":{"description":"Parameters to pass to the function.","type":"array","items":{"type":"string"}},"value":{"description":"Value in wei to send with the tx.","type":"string"},"fuzz":{"description":"Parameters to fuzz during the test.","type":"array","items":{"$ref":"#/components/schemas/FuzzParam"}},"kind":{"description":"Optional type of the spam transaction for categorization.","type":"string"},"gas_limit":{"description":"Optional gas limit, which will skip gas estimation. This allows reverting txs to be sent.","type":"integer"},"blob_data":{"description":"Optional blob data; tx type must be set to EIP4844 by spammer","type":"string"},"authorization_address":{"description":"Optional setCode data; tx type must be set to EIP7702 by spammer","type":"string"},"access_list":{"description":"Optional EIP-2930 access list entries to include in the transaction.","type":"array","items":{"$ref":"#/components/schemas/AccessListItem"}},"for_all_accounts":{"description":"If true and `from_pool` is set, run this setup transaction for all accounts in the pool. Defaults to false (only runs for the first account).","type":"boolean"}},"required":["to","for_all_accounts"]}, "FundAccountsParams": {"type":"object","properties":{"sessionId":{"type":"integer"},"agentClass":{"$ref":"#/components/schemas/AgentClass"},"amount":{"type":"string"}},"required":["sessionId","amount"]}, "FuzzParam": {"type":"object","properties":{"param":{"description":"Name of the parameter to fuzz.","type":"string"},"value":{"description":"Fuzz the `value` field of the tx (ETH sent with the tx).","type":"boolean"},"min":{"description":"Minimum value fuzzer will use.","type":"string"},"max":{"description":"Maximum value fuzzer will use.","type":"string"}}}, "RevertCliArgs": {"type":"object","properties":{"gas_use":{"description":"Amount of gas to use before reverting.","type":"integer"}},"required":["gas_use"]},